- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Python 脚本,它使用 subprocess.Popen
调用另一个 Python 脚本。我知道被调用的代码总是返回 10 ,这意味着它失败了。
我的问题是,调用者只有大约 75% 的时间读取 10。其他 25% 它读取 0 并将调用的程序失败代码误认为是成功。相同的命令,相同的环境,显然是随机发生的。
环境:Python 2.7.10,Linux Redhat 6.4。此处提供的代码是(非常)简化的版本,但我仍然可以使用它重现问题。
这是被调用的脚本,constant_return.py:
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
"""
Simplified called code
"""
import sys
if __name__ == "__main__":
sys.exit(10)
这是调用者代码:
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
"""
Simplified version of the calling code
"""
try:
import sys
import subprocess
import threading
except Exception, eImp:
print "Error while loading Python library : %s" % eImp
sys.exit(100)
class BizarreProcessing(object):
"""
Simplified caller class
"""
def __init__(self):
"""
Classic initialization
"""
object.__init__(self)
def logPipe(self, isStdOut_, process_):
"""
Simplified log handler
"""
try:
if isStdOut_:
output = process_.stdout
logfile = open("./log_out.txt", "wb")
else:
output = process_.stderr
logfile = open("./log_err.txt", "wb")
#Read pipe content as long as the process is running
while (process_.poll() == None):
text = output.readline()
if (text != '' and text.strip() != ''):
logfile.write(text)
#When the process is finished, there might still be lines remaining in the pipe
output.readlines()
for oneline in output.readlines():
if (oneline != None and oneline.strip() != ''):
logfile.write(text)
finally:
logfile.close()
def startProcessing(self):
"""
Launch process
"""
# Simplified command line definition
command = "/absolute/path/to/file/constant_return.py"
# Execute command in a new process
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
#Launch a thread to gather called programm stdout and stderr
#This to avoid a deadlock with pipe filled and such
stdoutTread = threading.Thread(target=self.logPipe, args=(True, process))
stdoutTread.start()
stderrThread = threading.Thread(target=self.logPipe, args=(False, process))
stderrThread.start()
#Wait for the end of the process and get process result
stdoutTread.join()
stderrThread.join()
result = process.wait()
print("returned code: " + str(result))
#Send it back to the caller
return (result)
#
# Main
#
if __name__ == "__main__":
# Execute caller code
processingInstance = BizarreProcessing()
aResult = processingInstance.startProcessing()
#Return the code
sys.exit(aResult)
这是我在 bash 中键入的内容以执行调用者脚本:
for res in {1..100}
do
/path/to/caller/script.py
echo $? >> /tmp/returncodelist.txt
done
它似乎与我读取被调用程序输出的方式有某种联系,因为当我使用 process = subprocess.Popen(command, shell=True, stdout=sys.stdout, stderr=sys 创建子进程时.stderr)
并删除它读取正确返回码的所有 Thread 内容(但不再按我想要的方式记录...)
知道我做错了什么吗?
非常感谢您的帮助
最佳答案
logPipe 还检查进程 是否处于事件状态以确定是否有更多数据要读取。这是不正确的 - 您应该通过查找零长度读取或使用 output.readlines() 来检查 pipe 是否已达到 EOF。 I/O 管道的生命周期可能比进程长。
这大大简化了 logPipe:如下更改 logPipe:
def logPipe(self, isStdOut_, process_):
"""
Simplified log handler
"""
try:
if isStdOut_:
output = process_.stdout
logfile = open("./log_out.txt", "wb")
else:
output = process_.stderr
logfile = open("./log_err.txt", "wb")
#Read pipe content as long as the process is running
with output:
for text in output:
if text.strip(): # ... checks if it's not an empty string
logfile.write(text)
finally:
logfile.close()
其次,在 process.wait() 之前不要加入您的日志记录线程,出于同样的原因 - I/O 管道可能会比进程长。
我认为幕后发生的事情是发出了一个 SIGPIPE 并在某处处理不当 - 可能被误解为进程终止条件。这是因为管道在一端或另一端被关闭而没有被冲洗。 SIGPIPE 有时在较大的应用程序中会很麻烦;可能是 Python 库吞下了它或者用它做了一些幼稚的事情。
编辑 正如@Blackjack 指出的那样,SIGPIPE 会自动被 Python 阻止。因此,这排除了 SIGPIPE 渎职行为。第二种理论:Popen.poll() 背后的文档指出:
Check if child process has terminated. Set and return returncode attribute.
如果您对其进行 strace(例如,strace -f -o strace.log ./caller.py
),这似乎是通过 wait4(WNOHANG) 完成的。您有 2 个线程使用 WNOHANG 等待,一个正常等待,但只有一个调用会正确返回进程退出代码。如果在 subprocess.poll() 的实现中没有锁定,那么很可能会出现分配 process.resultcode 的竞争,或者可能无法正确执行。将 Popen.waits/polls 限制为单个线程应该是避免这种情况的好方法。请参阅 man waitpid
。
编辑 顺便说一句,如果您可以将所有 stdout/stderr 数据保存在内存中,则 subprocess.communicate() 会更容易使用,并且根本不需要 logPipe 或后台线程。
https://docs.python.org/2/library/subprocess.html#subprocess.Popen.communicate
关于Python 子进程 : read returncode is sometimes different from returned code,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31539749/
我知道这类问题已经得到解答,但就我而言,我已经尝试了所有配置,但仍然不起作用。我需要对我的配置有一个新的看法(我确信我错过了一些东西)。两个附加程序都会记录所有级别 我想将所有包的信息 >= 记录到控
我正在对 Windows 移动设备上的代码性能进行一些基准测试,并注意到某些算法在某些主机上的表现明显更好,而在其他主机上则明显更差。当然,考虑到时钟速度的差异。 供引用的统计数据(所有结果均由同一个
我有一个程序可以计算多边形的面积和周长。程序还会确认面积和周长的计算结果是否与预期结果相同。 我不明白发生了什么,但确认面积和周长是否与预期相同的验证部分无法正常工作。 例如,我现在测试并在所有情况下
Codepen :(对于那些想直接进入的人来说,这是一个代码笔。在 Chrome 和 IE 中尝试一下,看看结果的不同) 我正在尝试使用 css3 转换/过渡,因为它们比 jquery 效果更流畅。
我有几个不同的正则表达式要在给定文本中匹配和替换。 regex1 :如果文本包含单词“Founder”,则将所有文本替换为首席执行官 正则表达式2:如果文本包含9位数字,则将其替换为NUM 我尝试使用
我编写了多线程应用程序,它从每个线程的数据库连接到一些电子邮件帐户。我知道 JavaMail 没有任何选项可以使用 SOCKS5 进行连接,因此我决定通过 System.setProperty 方法使
如您所见,这是我当前 Storyboard的不同设备预览。底部的透明绿色被另一个 View Controller 占用,但需要为每个不同的尺寸类固定间距。我尝试将 Storyboard 中的宽度和高度
我正在创建一个游戏,我需要能够改变玩家 Sprite 的速度。我认为最好的选择是通过重力影响 Sprite 。为了给用户运动的感觉,我希望背景以完全相同的速度向相反的方向移动。 我怎样才能给背景一个不
我正在查看BTrees库并注意到有多个 TreeSet (和其他)类,例如 BTrees.IOBTree.TreeSet BTrees.OOBTree.TreeSet BTrees.LFBTree.T
我有一个小型 C++ 库,必须为 armeabi 和 armeabi7a 编译。我还有一个非常大的 c++ 库,只需要为 armeabi 编译。现在正在为两种架构编译它们(使用 NDK),但这使我的
我需要根据站点的当前部分稍微更改主题。 似乎 MuiThemeProvider 只在加载时设置 muiTheme;但需要在 props 变化时更新。 如何做到这一点? 最佳答案 您可以尝试将主题放在包
如何创建两个每个都有自己的计数器的 lSTListing 环境? 如果我使用例如 \lstnewenvironment{algorithm}[2]{ \renewcommand\lstlist
我想使用 Travis-CI 和 Github 基于分支设置部署。 IE。 - 如果我们从 develop 构建- 然后执行 /deploy.rb使用 DEV 环境主机名,如果 master - 然后
我有一个带有数据验证的 WPF MVVM 数据表单窗口。很多控件都是文本框。目前,数据绑定(bind)触发器设置为默认值,即。 e.失去焦点。这意味着仅在可能完全填写字段时才对其进行验证。所以当删除一
我有许多应用程序的内容页面,并最终为每个内容页面编写了很多 View 模型。例如。如果我有一个包含项目组的列表,我将有一个 ShowAllViewModel并绑定(bind)到内容页面和列表中单个项目
我有一个通用 View 和 4 个其他 View 。我在通用 View 中使用 Bootstrap 选项卡(导航选项卡)。我希望其他 4 个 View 成为通用 View 中 4 个选项卡的内容。由于
我希望针对 Maven 发布插件的不同目标有不同的配置选项。故事是这样的: 我正在将 Git 用于 SCM。我希望release:prepare插件在本地完成所有操作,并让release:perfor
我正在为一个项目使用AbstractTableModel制作一个自定义TableModel,并且我需要找到一种方法让复选框显示在某些行上,而不是其他行上。我已经实现了 getColumn 方法,但我希
摘自《Javascript 忍者的 secret 》一书: EVENTS ARE ASYNCHRONOUS Events, when they happen, can occur at unpredi
我正在尝试配置我的第一个 GWT 记录器,到目前为止,我已经将日志消息打印到我的 JS 控制台(FF 的 Firebug): 最终,我希望非SEVERE 消息转到consoleHa
我是一名优秀的程序员,十分优秀!