我正在尝试从纯粹的stderr或拦截脚本并捕获其异常来获取python堆栈跟踪和错误的属性。无论哪种方式都没关系。这可能是一个XY问题,因此欢迎替代方案。
我目前正在编写一个程序,重定向参数以调用另一个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
我不确定是否有任何现有方法支持这两个计划中的任何一个。我知道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.
所以我想也许我们可以解析stderr并看看会发生什么。
我知道我们可以使用subprocess.run(..., check=True)
运行子进程来获取subprocess.SubprocessError
,但由于子进程可以是任何东西(不仅仅是python进程),我们实际上无法拦截发生了实际的异常。
将python文件作为模块加载到此文件中的一个问题是我们无法提供必要的参数,除非我们能以某种方式欺骗从底层脚本运行的sys.argv[]
或argparse
。可能有if __name__ == "__main__":
的脚本也不会执行,除非我们也这样做。
有什么想法吗?
答案 0 :(得分:2)
我更喜欢方法#2。我尽可能避免使用subprocess
或system
从Python调用Python。
更改sys.argv
的值很简单 - 您只需使用常规分配覆盖它。
欺骗__name__ == "__main__"
条件更难。不幸的是,这可能意味着您无法以通常的方式导入模块。根据{{3}},您可以使用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)
现在您可以捕获模块抛出的任何未捕获的异常,并在except
内按照您的喜好处理它们。