简体   繁体   English

从子流程重构或捕获python错误

[英]Reconstructing or catching python errors from subprocess

I'm currently trying to get attributes of a python stack trace and error from either purely the stderr or intercepting a script and catching its Exception. 我目前正试图从纯stderr或拦截脚本并捕获其Exception来获取python堆栈跟踪和错误的属性。 Either way is fine. 两种方法都可以。 This may be an XY problem so alternatives are welcome. 这可能是XY问题,因此欢迎您选择其他方法。

I am currently writing a program that kind of, redirects the arguments to call another python script: 我目前正在编写一种程序,将参数重定向以调用另一个python脚本:

import sys, subprocess
pyargs = sys.argv[1:] # Suppose pyargs is something like ["a.py", "123"]
result = subprocess.run(["python"] + pyargs, stdout=subprocess.PIPE, 
    stderr=subprocess.PIPE)
error = result.stderr # do something with this

Approach 1: Parsing dump 方法1:解析转储

I'm not sure whether there is any existing method that supports either of the two plans. 我不确定是否有支持两个计划中任何一个的现有方法。 I know that the python error dump is displayed in a very formulaic way: 我知道python错误转储以非常公式化的方式显示:

import sys, traceback
exc_type, exc_value, exc_traceback = sys.exc_info() # shows formatting
traceback.print_exc() # prints the stderr of what we wanted.

And so I thought perhaps we could parse the stderr and see what happens. 所以我想也许我们可以解析stderr并看看会发生什么。

Approach 2: Catching exception 方法2:捕获异常

I know that we can run subprocess with subprocess.run(..., check=True) to get the subprocess.SubprocessError , but since the subprocess can be anything(not just a python process), we can't actually intercept the actual exception that occurred. 我知道我们可以使用subprocess.run(..., check=True)运行子subprocess.run(..., check=True)来获取subprocess.SubprocessError ,但是由于子流程可以是任何东西(不仅是python流程),因此我们实际上无法拦截实际的发生的异常。

One issue with loading in the python file as a module to this file, is that we cannot supply the necessary arguments, unless we can somehow spoof the sys.argv[] or argparse that's running from the underlying script. 将python文件作为模块加载到此文件的一个问题是,我们无法提供必要的参数,除非我们能够以某种方式欺骗从底层脚本运行的sys.argv[]argparse Scripts that may have if __name__ == "__main__": will not execute either unless we spoof that too. if __name__ == "__main__":可能具有的脚本也不会执行,除非我们也欺骗了它。

Any ideas? 有任何想法吗?

I prefer approach #2. 我更喜欢方法2。 Whenever possible, I avoid using subprocess or system to call Python from Python. 尽可能避免使用subprocesssystem从Python调用Python。

Changing the value of sys.argv is easy - you just overwrite it using regular assignment. 更改sys.argv的值很容易-您只需使用常规分配将其覆盖即可。

Tricking the __name__ == "__main__" conditional is harder. 欺骗__name__ == "__main__"条件比较困难。 Unfortunately, it probably means that you can't simply import the module in the usual way. 不幸的是,这可能意味着您不能简单地以通常的方式导入模块。 According to How to import a module as __main__ ? 根据如何将模块作为__main__导入? , you can use the runpy module to execute your module and supply whatever value of __name__ you like. ,您可以使用runpy模块执行模块并提供所需的__name__值。

import runpy
import sys
sys.argv = ["C:/", "foo", "bar"]
try:
    runpy.run_module("yourmodulename", {}, "__main__")
except Exception as e:
    print("caught exception:", e)

Now you can catch any uncaught exceptions that your module throws, and handle them however you like within the except . 现在,您可以捕获模块引发的所有未捕获的异常,并根据需要在except处理它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM