views:

2168

answers:

4

I am creating a little dashboard for a user that will allow him to run specific jobs. I am using Django so I want him to be able to click a link to start the job and then return the page back to him with a message that the job is running. The results of the job will be emailed to him later.

I believe I am supposed to use subprocess.Popen but I'm not sure of that. So in pseudocode, here is what I want to do:

if job == 1:
    run script in background: /path/to/script.py
    return 'Job is running'
+21  A: 
p = subprocess.Popen([sys.executable, '/path/to/script.py'], 
                                    stdout=subprocess.PIPE, 
                                    stderr=subprocess.STDOUT)

That will start the subprocess in background. Your script will keep running normally.

Read the documentation here.

nosklo
nosklo: Thanks. How would I pass in arguments to the script?
sheats
Additional elements in the list passed as the first argument. The linked documentation is useful, and linked to for a reason.
Devin Jeanpierre
In a non-windows environment, you could check out os.fork as well
bothie
Devin: Thanks. I ask on here because it was hard for me to figure that out from the docs. I don't see sys.executable anywhere in the docs. If all we ever needed was docs, we wouldn't need SO =)
sheats
@sheats: sys.executable is documented here http://docs.python.org/library/sys.html#sys.executable
nosklo
@nosklo Is this a good thing to do in the context of a web server? I've seen advice to run a separate service for long-running jobs and communicate with a queue mechanism.
akaihola
@akaihola, it seems to be the original question. sheats is asking for a way to run a separate process (outside the webserver process). A communication mechanism was not part of the question.
nosklo
+1  A: 

subprocess.Popen is indeed what you are looking for.

Aaron Maenpaa
+1  A: 

Although if you find that you want to start communicating a bunch of information between the subprocess and the parent, you may want to consider a thread, or RPC framework like Twisted.

But most likely those are too heavy for your application.

Sean Cavanagh
+1  A: 

Running this through a message queue is definitely the way to go if you're thinking about long-term scaling. Send a message to the queue who's running constantly in the background, and write job handlers to deal with the different sorts of messages.

Since you're using Django, I think Beanstalkd is a pretty good fit. Here's a pretty nice tutorial on the subject. The first comment in that article also has some good tips.

Personally I've rolled with a custom in-memory queue server written in Erlang, with Python-bindings written in C. But redis looks like it might work out as a great contender for future queuing/messaging-needs. Hope this helps!

Henrik Lied
celery (http://pypi.python.org/pypi/celery) would also be a good match for this. It uses RabbitMQ (for the message persistence, a beanstalkd backend for carrot is certainly possible if someone has the time) The beanstalkd tutorial only solves one of the problems, sending messages, but leaves actually executing the task as an exercise for the reader.
asksol