Python:引发子异常,OSError:[Errno 2]没有这样的文件或目录。

20

我使用 subprocess.popen() 函数来执行 Python 命令,代码如下:

omp_cmd = 'cat %s | omp -h %s -u %s -w %s -p %s -X -' %(temp_xml, self.host_IP, self.username, self.password, self.port)
xmlResult = Popen(omp_cmd, stdout=PIPE, stderr=STDOUT)

在shell中它能够正常运行,但在Python中会出错:

  File "/home/project/vrm/apps/audit/models.py", line 148, in sendOMP
    xmlResult = Popen(omp_cmd, stdout=PIPE, stderr=STDOUT)
  File "/usr/local/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/local/lib/python2.7/subprocess.py", line 1228, in _execute_child
    raise child_exception
  OSError: [Errno 2] No such file or directory

我在搜索这个错误,但是没有解决我的问题。有人知道这个问题的原因吗?

2个回答

26

如果您要将命令作为字符串传递给Popen,并且如果这些命令中有管道连接到其他命令,则需要使用shell=True关键字。

我对omp命令不是特别熟悉,但这似乎很像无用的cat命令。我认为更好的方法是:

import shlex
omp_cmd = 'omp -h %s -u %s -w %s -p %s -X %s' \
%(self.host_IP, self.username, self.password, self.port, temp_xml)
xmlResult = Popen(shlex.split(omp_cmd), stdout=PIPE, stderr=STDOUT)

或者,如果它不是一种无用的使用cat(您确实需要通过stdin将文件管道传入),您也可以使用subprocess来执行此操作:

import shlex
omp_cmd = 'omp -h %s -u %s -w %s -p %s -X -' \
%(self.host_IP, self.username, self.password)
with open(temp_xml) as stdin:
    xmlResult = Popen(shlex.split(omp_cmd), stdin=stdin, 
    stdout=PIPE, stderr=STDOUT)

你说得对!!还有一个问题,如果shell=False,那么args应该是一个列表,对吗?这两种方式有什么区别? - Shang Wang
1
回答你的问题,我存储在文件中的那个命令有9000行,我的操作系统会显示“参数列表太长错误” :) - Shang Wang
2
@da_zhuang -- 是的,当使用shell=False时,参数通常是一个列表。我使用了shlex.split函数,该函数将字符串分割成列表,就像典型的shell一样。当使用shell=True时,你传递一个字符串,该字符串由shell进行评估。当使用shell=False时,你可以传递一个字符串或者一个列表。如果传递一个字符串,则它被视为唯一的命令。("ls -l"将会失败,因为没有ls -l这个命令,只有ls)。如果传递一个列表,则将每个元素作为一个参数。["ls", "-l"] - mgilson
@da_zhuang -- 我已经编辑了一个版本,保留了从stdin读取原始内容的功能,但仍然删除了对cat的依赖,因此无需使用shell=Trueshell=True的问题在于,如果给出不受信任的输入,它容易受到shell注入攻击。(比如说,如果self.host_IP被分配了值"; rm -rf ~;") - mgilson

0

我也遇到了使用tox脚本时出现的这个错误,原来是tox创建了一个虚拟环境,其绝对路径长度约为96个字符,但当它接近123个字符时,会出现调用错误OSError2。

'ERROR: invocation failed (errno 2), OSError: [Errno 2] No such file or directory'

Python版本:Python 2.7.6 virtualenv版本:15.1.0 tox版本:2.9.1 pip版本:9.0.1 Ubuntu版本:14.04 测试覆盖范围:django(1.8-1.11),每个版本都有py27和py35的测试

解决方法: 我首先创建了一个虚拟环境(绝对路径<=(96-100)个字符),在其中安装了tox,并克隆了要与此tox安装和虚拟环境一起使用的项目,现在tox创建了自己的虚拟环境并且可以正常运行。

希望能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接