管道子进程时资源不可用

时间:2017-07-26 11:49:20

标签: python python-3.x subprocess popen

我试图在不在PATH中时使用Python找到MATLAB可执行文件的路径。我使用subprocess.Popen来执行定位和grepping结果,但是这会创建一个Resource Unavailable错误:

locate = subprocess.Popen(['locate', 'matlab'], stdout=subprocess.PIPE)
grep = subprocess.Popen(['grep', '/bin/matlab$'], stdin=locate.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result, err = grep.communicate()
MATLAB_PATH = result.decode('UTF-8').split()

结果变量为空,错误变量为:

b'grep: (standard input): Resource temporarily unavailable\n'

2 个答案:

答案 0 :(得分:1)

我已经使用python 3.5.2和3.6.1在Linux上尝试过你的代码,它确实有效:

locate = subprocess.Popen(['locate', 'find'], stdout=subprocess.PIPE)
grep = subprocess.Popen(['grep', '/bin/find$'], stdin=locate.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
grep.communicate()
(b'/usr/bin/find\n', b'')

对于记录:locate find给出了1619行。 为了完整起见,我还尝试了locate fdafad(乱码),它也有效。

当代码在脚本中时,它也可以工作。

修改

尝试使用沟通来交互两个进程:

locate = subprocess.Popen(['locate', 'find'], stdout=subprocess.PIPE)
stdout, stderr = locate.communicate()
grep = subprocess.Popen(['grep', '/bin/find$'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(grep.communicate(input=stdout))

注意:答案的第二部分是在之前写的,提问者用PATH

的相关信息更新了问题

然而,使用python找到可执行文件有更好的方法:

from distutils.spawn import find_executable
find_executable('find')

'/usr/bin/find'

如果你坚持使用shell函数,为什么不使用像which这样的东西。

答案 1 :(得分:1)

仅添加有关此错误发生原因的更多信息。

eventlet使用" green"这似乎是一个问题。线程和非阻塞IO并找到生成足够快的输出。也就是说,eventlet假定stdout将由python使用。 Eventlet使用非阻塞IO来协助协作线程。这意味着您传递给locate.stdout的{​​{1}}后面的文件描述符已设置为非阻塞。如果grep在空的时候尝试从stdin读取,那么你将得到该错误。

一个简单的解决方案是在一个shell中执行这两个命令(因此Python不会弄乱两个子进程之间的管道)。

例如

grep