在Python 2.5及更低版本上不使用shell创建可执行进程

时间:2009-09-10 22:07:42

标签: python process fork subprocess popen

正如标题所说:

  1. subprocess模块无法使用,因为这应该适用于2.4和2.5
  2. 不应生成Shell进程来传递参数。
  3. 要解释(2),请考虑以下代码:

    >>> x=os.system('foo arg')
    sh: foo: not found
    >>> x=os.popen('foo arg')
    sh: foo: not found
    >>> 
    

    如您所见os.systemos.popen通过系统shell(“sh”)运行给定命令(“foo”)。我不希望这种情况发生(否则,在没有我控制的情况下,将丑陋的“未找到”消息打印到程序stderr上。)

    最后,我应该能够将参数传递给这个程序(上例中的'arg')。

    如何在Python 2.5和2.4中执行此操作?

2 个答案:

答案 0 :(得分:3)

您可能需要使用Python 2.4中提供的子进程模块

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

您需要包含完整路径,因为您没有使用shell。

http://docs.python.org/library/subprocess.html#replacing-os-system

或者,您也可以将subprocess.PIPE传递给stderr和stdout以抑制消息。有关详细信息,请参阅上面的链接。

答案 1 :(得分: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"])

您还可以使用已在子进程模块中定义的这两个便捷函数:

# Their arguments are the same as the Popen constructor
retcode = subprocess.call(["echo", "2"])
subprocess.check_call(["echo", "2"])

请记住,您可以将stdout和/或stderr重定向到PIPE,因此不会将其打印到屏幕上(但输出仍可供您的python阅读程序)。默认情况下,stdoutstderr都是None,这意味着无重定向,这意味着他们将使用与您的python程序相同的stdout / stderr。< / p>

此外,您可以使用shell=True并将stdoutstderr重定向到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)