I need to run a shell command asynchronously from a Python script. By this I mean that I want my Python script to continue running while the external command goes off and does whatever it needs to do.
I read this post:
I then went off and did some testing, and it looks like os.system()
will do the job provided that I use &
at the end of the command so that I don't have to wait for it to return. What I am wondering is if this is the proper way to accomplish such a thing? I tried commands.call()
but it will not work for me because it blocks on the external command.
Please let me know if using os.system()
for this is advisable or if I should try some other route.
I have the same problem trying to connect to an 3270 terminal using the s3270 scripting software in Python. Now I'm solving the problem with an subclass of Process that I found here:
http://code.activestate.com/recipes/440554/
And here is the sample taken from file:
Considering "I don't have to wait for it to return", one of the easiest solutions will be this:
But... From what I read this is not "the proper way to accomplish such a thing" because of security risks created by
subprocess.CREATE_NEW_CONSOLE
flag.The key things that happen here is use of
subprocess.CREATE_NEW_CONSOLE
to create new console and.pid
(returns process ID so that you could check program later on if you want to) so that not to wait for program to finish its job.Using pexpect [ http://www.noah.org/wiki/Pexpect ] with non-blocking readlines is another way to do this. Pexpect solves the deadlock problems, allows you to easily run the processes in the background, and gives easy ways to have callbacks when your process spits out predefined strings, and generally makes interacting with the process much easier.
If you want to run many processes in parallel and then handle them when they yield results, you can use polling like in the following:
The control flow there is a little bit convoluted because I'm trying to make it small -- you can refactor to your taste. :-)
This has the advantage of servicing the early-finishing requests first. If you call
communicate
on the first running process and that turns out to run the longest, the other running processes will have been sitting there idle when you could have been handling their results.subprocess.Popen does exactly what you want.
(Edit to complete the answer from comments)
The Popen instance can do various other things like you can
poll()
it to see if it is still running, and you cancommunicate()
with it to send it data on stdin, and wait for it to terminate.What I am wondering is if this [os.system()] is the proper way to accomplish such a thing?
No.
os.system()
is not the proper way. That's why everyone says to usesubprocess
.For more information, read http://docs.python.org/library/os.html#os.system