I regularly come across code such as:
output = os.popen('diff -u %s %s' % (appl_file, ref_file), 'r')
Code like this might well work machine but it is buggy and will fail (preferably during the demo or once shipped).
Where is the bug?
It is in the use of %s, which can inject in your command any string you want and also strings you don't want. The problem is that you probably did not check appl_file and ref_file for weird things (spaces, quotes, semi colons...). Putting quotes around the %s in the string will not solve the issue.
So what should you do? The answer is "use the subprocess module": subprocess.Popen takes a list of arguments as first parameter, which are passed as-is to the new process creation system call of your platform, and not interpreted by the shell:
pipe = subprocess.Popen(['diff', '-u', appl_file, ref_file], stdout=subprocess.PIPE) output = pipe.stdout
By now, you should have guessed that the shell=True parameter of subprocess.Popen should not be used unless you really really need it (and even them, I encourage you to question that need).
- logilab-xmltools High level tools to help using XML in Python
- The Python Package Index is not a "Software Distribution"
- qgpibplotter is (hopefully) working
- pyreverse http://www.logilab.org/project/pylint a set of tools for reverse engineering Python code.
- Reinteract: un outil intéressant pour faire du numpy/scipy
Comments
But the other code is so much more 'beautiful', at least I think so :)
Subprocess is so hard to use. I can always add a few hours to any schedule to get the flags correct for multiple operating systems. And basically, shell=True is required to make anything work, except on Osx where it only breaks things.
write down the correct flags once for all and share!
If the binary you want to execute does not have exec bit turned on, you should do cmd = '/bin/sh' + cmd on UNIX. The retcode = call( ['ls', '-l'] is the short version I use now to replace an os.system()
os.environ['arg1'] = "something"
os.environ['arg2'] = "something else"
os.system('command "$arg1" "$arg2"')
That looks even worse than subprocess
you can't be serious!