binarymatt / pyres

a resque clone in python
http://github.com/binarydud/pyres
MIT License
955 stars 130 forks source link

NoneType has no perform method #13

Closed yashh closed 14 years ago

yashh commented 14 years ago

I have a python project where I have {pyres, resweb, scripts} in resque folder. Whenever I put a job in the queue I do

>>> from resque.pyres import ResQ
>>> r = ResQ()
>>> r.enqueue(Someclass, "hello")

I am sure "Someclass" class has a perform method on it which prints the arg. But when the job is picked up it fails with error

NoneType has no perform method

When I have pyres in my project root it works. Just dont get why this is failing.

binarymatt commented 14 years ago

is your "Someclass" on your python path? It sounds like pyres can't import it when it tries to work on the job.

yashh commented 14 years ago

ok here is my real example.

 -- project.py
 -- project_app
   |
   ---   app.py
   ---   tasks.py
 --  resque
      |
      ---  pyres
      --- resweb
      --- pyres_worker
      --- pyres_web

So all my Tasks which are to be run on the queue are in tasks.py. "Someclass" I defined is in tasks.py. I am putting a task on the queue in app.py.

project.py contains all my urls and Handlers which handle each url. All my handlers are in project_app/app.py. In my project.py i put resque on sys.path

PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(PROJECT_ROOT, 'resque'))

The job is succesfully put on the queue. But worker fails

{"queue": "javascript", "payload": {"args": ["library", "prototypejs", {"url": "http://prototypejs.org", "description": null, "tags": null, "name": "prototypejs", "author": "23"}], "class": "project.tasks.IndexUpdate"}, "run_at": "2010-01-10 20:11:03.066770"} <pyres.job.Job object at 0x1007b32d0> failed: 'NoneType' object has no attribute 'perform'

mjrusso commented 14 years ago

binarydud, I just forked pyres and made a change that allows the user to specify (via the command-line interface used to launch workers) how they want the python path modified.

The commit is on a new branch called modify_sys_path. See here: http://github.com/mjrusso/pyres/commit/7d21341f5810f0286d2e9b0365a447591453aa70

Usage example:

INCLUDES=/code/worker/needs pyres_worker default

yashh, adding resque to the sys path is not the solution to your problem. You need to tell pyres_worker where the code in project_app is.

mjrusso commented 14 years ago

Instead of the INCLUDES patch, the following is a better approach (thanks binarydud):

PYTHONPATH=$PYTHONPATH:/code/worker/needs pyres_worker default

No code change required.

yashh commented 14 years ago

@mjrusso thanks for the includes. The PYTHONPATH seems to be same solution.

The worker also needs an option load the app code so that it can call function from the app.

Example: Ability to set DJANGO SETTINGS variable .

binarymatt commented 14 years ago

Yashh, I'm at pycon this weekend, but if I have time, I will try and post an example that sets up django from within a perform method and also an example that sets up django before the worker is started

binarymatt commented 14 years ago

I'm going to close this ticket now. As for the django items, i've put a page called external settings on the wiki. I'll be happy to answer any more questions about this on the mailing list.

robbiehudson commented 14 years ago

Happy to create another ticket for this but would it not make sense to raise an exception when the class isn't found? I'm willing to create a patch for this if required...

binarymatt commented 14 years ago

let's go ahead an open another ticket for raising an exception when the class isn't found. The more I think about it, the more that sounds like a good idea