管道子流程时资源不可用
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 来辅助协作线程。这意味着您传递给 grep
的 locate.stdout
后面的文件描述符已经设置为非阻塞。如果 grep
尝试在标准输入为空时读取它,那么您将收到该错误。
一个简单的解决方案是在一个 shell 中执行这两个命令(因此 Python 不会弄乱两个子进程之间的管道)。
例如
result = subprocess.check_output('locate matlab | grep /bin/matlab$', shell=True).strip()
我正在尝试使用 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 来辅助协作线程。这意味着您传递给 grep
的 locate.stdout
后面的文件描述符已经设置为非阻塞。如果 grep
尝试在标准输入为空时读取它,那么您将收到该错误。
一个简单的解决方案是在一个 shell 中执行这两个命令(因此 Python 不会弄乱两个子进程之间的管道)。
例如
result = subprocess.check_output('locate matlab | grep /bin/matlab$', shell=True).strip()