我必须在大约300个目录上运行一个工具。每次运行大约需要1分钟到30分钟甚至更长时间。所以,我编写了一个python脚本,它有一个循环来一个接一个地在所有目录上运行该工具。
我的python脚本的代码如下:
for directory in directories:
os.popen('runtool_exec ' + directory)
但是当我运行python脚本时,我反复收到以下错误消息:
..
tail: write error: Broken pipe
date: write error: Broken pipe
..
我所做的就是使用ssh登录远程服务器,其中保存了工具,python脚本和主题目录。当我使用以下命令从命令提示符单独运行该工具时:
runtool_exec directory
它工作正常。只有当我使用python脚本运行时,“破管”错误才会出现。 任何想法,解决方法?
答案 0 :(得分:9)
您看到的错误是因为您使用os.popen()
来运行命令,这意味着管道已打开并连接到命令stdout
。每当命令(或其执行的任何内容而不重定向stdout
)想要写入stdout
时,它都会尝试写入管道。但是你没有保留管道,因为你没有在任何地方分配os.popen()
的结果,所以它被Python清理并关闭。因此,尝试写入它的进程遇到管道损坏,并产生您看到的错误。 (os.popen()
不将stderr
重定向到管道,因此您仍然会看到错误。)
os.popen()
来电中的另一个问题是您没有检查以确保directory
不包含shell特有的任何字符。例如,如果目录包含引号,或者*,则可能会发生奇怪的事情。像这样使用os.popen()
非常糟糕。
你应该使用subprocess.Popen()
,并明确地告诉它你要对进程的输出(stdout和stderr)做什么。你传递subprocess.Popen()
一个参数列表(包括你想要的东西)开始)而不是单个字符串,它完全避免了shell - 不需要理智 - 检查你的字符串。如果你真的想忽略输出,你可以使用类似的东西:
devnull = open(os.devnull, 'w')
for directory in directories:
subprocess.Popen(['runtool_exec', directory], stdout=devnull)
虽然我强烈建议至少对subprocess.Popen的结果进行一些初步的检查,以查看进程是否过早执行或是否有错误代码。
答案 1 :(得分:0)
如果它对其他人有帮助,同样的问题可能是在shell命令中使用管道(|)的结果。请参阅此处了解解决方案https://stackoverflow.com/a/4106633/1904913