在Python 2.5及以下版本中创建不使用shell的可执行进程
标题说的就是这个:
- 不能使用
subprocess
模块,因为这个代码需要在 2.4 和 2.5 版本上运行。 - 不应该通过启动一个新的 shell 进程来传递参数。
为了说明第二点,看看下面的代码:
>>> x=os.system('foo arg')
sh: foo: not found
>>> x=os.popen('foo arg')
sh: foo: not found
>>>
如你所见,os.system
和 os.popen
是通过系统的 shell("sh")来运行给定的命令("foo")。我不想这样做(否则,程序会在错误输出中打印出难看的“找不到”消息,而我无法控制)。
最后,我应该能够把参数传递给这个程序(上面例子中的 'arg')。
那么,在 Python 2.5 和 2.4 中,应该怎么做呢?
2 个回答
0
如前所述,你可以(而且应该)使用 subprocess 模块。
默认情况下,shell
参数是 False
。这很好,而且相当安全。而且,你不需要传递完整的路径,只需传递可执行文件的名称和参数,作为一个序列(元组或列表)就可以了。
import subprocess
# This works fine
p = subprocess.Popen(["echo","2"])
# These will raise OSError exception:
p = subprocess.Popen("echo 2")
p = subprocess.Popen(["echo 2"])
p = subprocess.Popen(["echa", "2"])
你还可以使用 subprocess 模块中已经定义的这两个方便的函数:
# Their arguments are the same as the Popen constructor
retcode = subprocess.call(["echo", "2"])
subprocess.check_call(["echo", "2"])
记住,你可以将 stdout
和/或 stderr
重定向到 PIPE
,这样它们就不会打印到屏幕上(但输出仍然可以被你的 Python 程序读取)。默认情况下,stdout
和 stderr
都是 None
,这意味着 没有重定向,也就是说它们将使用与你的 Python 程序相同的 stdout/stderr。
此外,你可以使用 shell=True
并将 stdout
和 stderr
重定向到 PIPE,这样就不会打印任何消息:
# This will work fine, but no output will be printed
p = subprocess.Popen("echo 2", shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# This will NOT raise an exception, and the shell error message is redirected to PIPE
p = subprocess.Popen("echa 2", shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
3
你可能需要使用在Python 2.4中提供的subprocess模块。
Popen("/home/user/foo" + " arg")
>>> Popen("foo arg", shell=False)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/subprocess.py", line 595, in __init__
errread, errwrite)
File "/usr/lib/python2.6/subprocess.py", line 1092, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
因为你没有使用命令行,所以需要写出完整的路径。
http://docs.python.org/library/subprocess.html#replacing-os-system
另外,你也可以把subprocess.PIPE传给stderr和stdout,这样就可以屏蔽消息了。想了解更多细节,可以查看上面的链接。