[英]Python: catch exception from subprocess while iterating through stdout
我正在尝试从子流程中获取异常。 如果我使用.communicate
,我可以得到它,但我想避免使用它,因为我正在从子进程流输出,并且不想等到整个子进程完成。 还假设整个子流程可能需要很长时间。 想知道如何在从子进程流式传输标准输出时捕获抛出的异常。
考虑下面的例子,所以我想让版本 #1 工作,版本 #2 有点工作,但不希望那样。
在 main.py
import subprocess
class ExtProcess():
def __init__(self, *args):
self.proc = subprocess.Popen(['python', *args], stdout=subprocess.PIPE)
def __iter__(self):
return self
def __next__(self):
while True:
line = self.proc.stdout.readline()
if self.proc.returncode:
raise Exception("error here")
if not line:
raise StopIteration
return line
def run():
## version #1
reader = ExtProcess("sample_extproc.py")
for d in reader:
print(f"got: {d}")
## version #2
# proc = subprocess.Popen(['python', "sample_extproc.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# output, error = proc.communicate()
# print("got:", output)
# if proc.returncode:
# raise Exception(error)
def main():
try:
print("start...")
run()
print("complete...")
except Exception as e:
print(f"Package midstream error here: {str(e)}")
finally:
print("clean up...")
if __name__ == "__main__":
main()
在 sample_extproc.py 中
for x in range(10):
print(x)
if x == 3:
raise RuntimeError("catch me")
我想从版本 #1 获得类似下面的输出:
start...
got: b'0\r\n'
got: b'1\r\n'
got: b'2\r\n'
got: b'3\r\n'
Package midstream error here: b'Traceback (most recent call last):\r\n File "sample_extproc.py", line 4, in <module>\r\n raise RuntimeError("catch me")\r\nRuntimeError: catch me\r\n'
clean up...
基本上它遍历子进程的标准输出,然后在发生异常时打印异常,然后继续执行清理。
以下是我的问题的答案,实际上基于@CharlesDuffy 的评论:
总之,确保有stderr=subprocess.PIPE
在ExtProcess
类,那么答案是#3型,其中通过标准输出迭代后,我们利用.wait()
和returncode
,如果是这样,检查是否存在错误引发异常,从stderr.read()
获取要在父/主中捕获的错误。
import subprocess
class ExtProcess():
def __init__(self, *args):
self.proc = subprocess.Popen(['python', *args], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def __iter__(self):
return self
def __next__(self):
while True:
line = self.proc.stdout.readline()
if not line:
raise StopIteration
return line
def run():
## version #1
# reader = ExtProcess("sample_extproc.py")
# for d in reader:
# print(f"got: {d}")
## version #2
# proc = subprocess.Popen(['python', "sample_extproc.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# output, error = proc.communicate()
# print("got:", output)
# if proc.returncode:
# raise Exception(error)
## version #3
reader = ExtProcess("sample_extproc.py")
for d in reader:
print(f"got: {d}")
reader.proc.wait()
if reader.proc.returncode:
raise Exception(reader.proc.stderr.read())
def main():
try:
print("start...")
run()
print("complete...")
except Exception as e:
print(f"Package midstream error here: {str(e)}")
finally:
print("clean up...")
if __name__ == "__main__":
main()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.