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

2024-04-18 16:43:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在尝试从纯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

方法1:解析转储

我不确定是否有任何现有的方法支持这两个计划中的任何一个。我知道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,看看会发生什么

方法2:捕获异常

我知道我们可以用subprocess.run(..., check=True)运行子进程来获得subprocess.SubprocessError,但是由于子进程可以是任何东西(不仅仅是python进程),我们实际上无法截获发生的实际的异常

将python文件作为模块加载到此文件时的一个问题是,我们无法提供必要的参数,除非我们能够以某种方式欺骗从底层脚本运行的sys.argv[]argparse。可能有if __name__ == "__main__":的脚本也不会执行,除非我们也欺骗它

有什么想法吗


Tags: 方法import脚本参数进程错误stderrsys
1条回答
网友
1楼 · 发布于 2024-04-18 16:43:53

我更喜欢方法#2。只要可能,我都避免使用subprocesssystem从Python调用Python

更改sys.argv的值很容易-只需使用常规赋值覆盖它

欺骗__name__ == "__main__"条件更难。不幸的是,这可能意味着您不能以通常的方式简单地导入模块。根据How to import a module as ^{}?,您可以使用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中以您喜欢的方式处理它们

相关问题 更多 >