在Python 2.5及以下版本中创建不使用shell的可执行进程

1 投票
2 回答
1105 浏览
提问于 2025-04-15 14:14

标题说的就是这个:

  1. 不能使用 subprocess 模块,因为这个代码需要在 2.4 和 2.5 版本上运行。
  2. 不应该通过启动一个新的 shell 进程来传递参数。

为了说明第二点,看看下面的代码:

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

如你所见,os.systemos.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 程序读取)。默认情况下,stdoutstderr 都是 None,这意味着 没有重定向,也就是说它们将使用与你的 Python 程序相同的 stdout/stderr。

此外,你可以使用 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)
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,这样就可以屏蔽消息了。想了解更多细节,可以查看上面的链接。

撰写回答