管道子流程时资源不可用

Resource unavailable when piping subprocess

我正在尝试使用 Python 找到 MATLAB 可执行文件的路径,但它不在 PATH 中。我正在使用 subprocess.Popen 执行定位并搜索结果,但这会产生资源不可用错误:

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()

result 变量为空,err 变量为:

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

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

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))

注意:答案的第二部分已经写在之前提问者用关于[=15=的信息更新了问题]

然而,使用 python:

查找可执行文件有更好的方法
from distutils.spawn import find_executable
find_executable('find')

'/usr/bin/find'

如果你坚持使用shell函数,为什么不使用像which.

这样的函数呢?

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

这看起来是 eventlet 使用 "green" 线程和非阻塞 IO 的问题,并且找到 not 足够快地生成输出。也就是说,eventlet 假定标准输出将由 python 使用。 Eventlet 使用非阻塞 IO 来辅助协作线程。这意味着您传递给 greplocate.stdout 后面的文件描述符已经设置为非阻塞。如果 grep 尝试在标准输入为空时读取它,那么您将收到该错误。

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

例如

result = subprocess.check_output('locate matlab | grep /bin/matlab$', shell=True).strip()