|Friday, June 6, 2003|
A friend who is new to Python was complaining about the rather lacking feature set of Python's popen*() family of functions. Namely, they take a straight command line -- not a list of arguments -- and, as such, you have to escape everything yourself if you are at all interested in security, etc,etc,etc...
This is a problem that has annoyed me off and on, as well. I figured someone had to have written a shell escape function for Python. However, Google revealed nothing useful and neither did ActiveState's wonderful archive of recipes.
While searching, I did run across pexpect:
Pexpect is a pure Python module for spawning child applications; controlling them; and responding to expected patterns in their output. Pexpect works like Don Libes' Expect. Pexpect allows your script to spawn a child application and control it as if a human were typing commands.
# This connects to the openbsd ftp site and # downloads the recursive directory listing. import pexpect child = pexpect.spawn ('ftp ftp.openbsd.org') child.expect ('Name .*: ') child.sendline ('anonymous') child.expect ('Password:') child.sendline ('email@example.com') child.expect ('ftp> ') child.sendline ('cd pub') child.expect('ftp> ') child.sendline ('get ls-lR.gz') child.expect('ftp> ') child.sendline ('bye')
Very useful. To add to pexpect's value, the implementation is great. Not only does it "just work" and "just work" in a way that is easy to leverage in your own code, but the implementation accounts for numerous platform specific bugs and documents each one along with version information, a bug #, and/or an URL to find more information.
Internally, pexpect uses execvp() and passes arguments to the child process as an array. It will parse a regular, popen() style, command line or it can be passed an array of arguments. This addresses the need for shell escaping very cleanly.