从另一个python程序运行python程序(有一定要求) [英] Run python program from another python program (with certain requirements)

查看:157
本文介绍了从另一个python程序运行python程序(有一定要求)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个python脚本A.pyB.py.我正在寻找一种从A内部运行B的方式,使得:

Let's say I have two python scripts A.py and B.py. I'm looking for a way to run B from within A in such a way that:

  1. B认为它是__main__(这样B中if __name__=="__main__"块中的代码将运行)
  2. B实际上不是__main__(因此它不会例如覆盖sys.modules中的"__main__"条目)
  3. B中引发的异常会传播到A(即,可以在A中的except子句中捕获).
  4. 如果未捕获到这些异常,则会生成引用B中行号的正确回溯.
  1. B believes it is __main__ (so that code in an if __name__=="__main__" block in B will run)
  2. B is not actually __main__ (so that it does not, e.g., overwrite the "__main__" entry in sys.modules)
  3. Exceptions raised within B propagate to A (i.e., could be caught with an except clause in A).
  4. Those exceptions, if not caught, generate a correct traceback referencing line numbers within B.

我尝试了各种技术,但似乎没有一种能够满足我的所有要求.

I've tried various techniques, but none seem to satisfy all my requirements.

  • 使用子流程模块中的工具意味着B中的异常不会传播到A.
  • execfile("B.py", {})运行B,但它并不主要.
  • execfile("B.py", {'__name__': '__main__'})使B.py认为它是主要的,但它似乎也搞砸了异常回溯打印,因此回溯引用了A中的行(即真实的__main__).
  • 使用imp.load_source__main__作为名称几乎可以用,除了它实际上会修改sys.modules之外,从而踩了__main__的现有值
  • using tools from the subprocess module means exceptions in B do not propagate to A.
  • execfile("B.py", {}) runs B, but it doesn't think it's main.
  • execfile("B.py", {'__name__': '__main__'}) makes B.py think it's main, but it also seems to screw up the exception traceback printing, so that the tracebacks refer to lines within A (i.e., the real __main__).
  • using imp.load_source with __main__ as the name almost works, except that it actually modifies sys.modules, thus stomping on the existing value of __main__

有什么办法可以得到我想要的东西吗?

Is there any way to get what I want?

(这样做的原因是因为我正在对现有库进行一些清理.该库没有真正的测试套件,只是一组产生特定输出的示例"脚本.我试图利用这些作为测试,以确保清理不会影响库执行这些示例的能力,因此我想在测试套件中运行每个示例脚本.测试脚本,以便测试脚本可以报告失败的类型,而不仅仅是在示例脚本引发某些异常时才报告通用的SubprocessError.)

(The reason I'm doing this is because I'm doing some cleanup on an existing library. This library has no real test suite, just a set of "example" scripts that produce certain output. I'm trying to leverage these as tests to ensure that my cleanup doesn't affect the library's ability to execute these examples, so I want to run each example script from within my test suite. I'd like to be able to see exceptions from these scripts within the test script so the test script can report the type of failure, instead of just reporting a generic SubprocessError whenever an example script raises some exception.)

推荐答案

回答我自己的问题,因为结果很有趣并且可能对其他人有用:

Answering my own question because the result is kind of interesting and might be useful to others:

事实证明我错了:execfile("B.py", {'__name__': '__main__'}毕竟是要走的路.它确实正确地产生了回溯.我看到的错误行号不是异常,而是警告.这些警告是使用warnings.warn("blah", stacklevel=2)产生的. stacklevel=2参数应该允许在使用不赞成使用的东西的地方引发不赞成使用警告之类的事情,而不是在警告调用时发出(参见

It turns out I was wrong: execfile("B.py", {'__name__': '__main__'} is the way to go after all. It does correctly produce the tracebacks. What I was seeing with incorrect line numbers weren't exceptions but warnings. These warnings were produced using warnings.warn("blah", stacklevel=2). The stacklevel=2 argument is supposed to allow for things like deprecation warnings to be raised where the deprecated thing is used, rather than at the warning call (see the documentation).

但是,似乎execfile-d文件并不为此目的而被视为堆栈级",而对于stacklevel目的而言是不可见的.因此,如果execfile-d模块顶层的代码在堆栈级别2上引起警告,则该警告不会在execfile-d源文件的右行编号处引发;而是在运行execfile的文件的相应行号处引发它.

However, it seems that the execfile-d file doesn't count as a "stack level" for this purpose, and is invisible for stacklevel purposes. So if code at the top level of an execfile-d module causes a warning with stacklevel 2, the warning is not raised at the right line number in the execfile-d source file; instead it is raised at the corresponding line number of the file which is running the execfile.

这很不幸,但是我可以接受,因为这些只是警告,因此它们不会影响测试的实际性能. (起初我没有注意到只有警告受行号不匹配的影响,因为在测试输出中混杂了很多警告和异常.)

This is unfortunate, but I can live with it, since these are only warnings, so they won't impact the actual performance of the tests. (I didn't notice at first that it was only the warnings that were affected by the line-number mismatches, because there were lots of warnings and exceptions intermixed in the test output.)

这篇关于从另一个python程序运行python程序(有一定要求)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆