2012-07-06 100 views
5

假设我有两个python脚本A.pyB.py。我正在寻找一种方式来从A内以这样的方式运行B中:从另一个python程序运行python程序(有一定的要求)

  1. 乙认为这是__main__(所以在B中的if __name__=="__main__"块代码将运行)
  2. B是不实际(例如,它不覆盖sys.modules中的"__main__"条目)
  3. B中引发的异常传播给A(即,可能会被A中的except子句捕获)。
  4. 这些例外,如果不抓住,内B.

我已经试过各种方法产生正确的回溯引用的行号,但没有一个似乎满足我的所有要求。使用工具从子模块

  • 意味着B中的异常不会传播到A.
  • execfile("B.py", {})运行B,但并不认为这是主要的。
  • execfile("B.py", {'__name__': '__main__'})使B.py认为它是主要的,但它似乎也搞砸了异常追溯打印,以便追溯引用A中的行(即真实的__main__)。
  • 使用imp.load_source__main__因为几乎工程,但它实际上是修改sys.modules中,从而践踏的__main__

现有值的名称有什么办法让我想要什么?我之所以这样做是因为我正在对现有的库进行一些清理,这个库没有真正的测试套件,只是一组产生特定输出的“示例”脚本。为了确保我的清理不会影响库执行这些示例的能力,所以我想从我的测试套件中运行每个示例脚本。我希望能够在这些脚本中看到异常测试脚本使测试脚本可以报告失败类型,而不是仅在示例脚本引发一些异常时报告通用的SubprocessError。)

回答

2

回答我的问题,因为结果是很有趣,可能是有用的人:

事实证明我错了:execfile("B.py", {'__name__': '__main__'}是去后,所有的方式。它确实正确产生回溯。我看到的不正确的行号不是,例外,但警告。这些警告是使用warnings.warn("blah", stacklevel=2)生成的。 stacklevel=2参数应该允许在不使用弃用事件的情况下引发弃用警告,而不是在警告调用(请参阅the documentation)。

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

这很不幸,但我可以忍受它,因为这些只是警告,所以它们不会影响测试的实际性能。 (我一开始并没有注意到它只是受线数不匹配影响的警告,因为在测试输出中混合了很多警告和例外。)

+0

有趣的解决方案。我怀疑(并希望..)我会永远需要它,但python允许和启用的东西有点酷。 – 2012-07-06 11:23:46

2

您的用例有道理,但我仍然认为您的状况会更好重构测试,以便它们可以在外部运行。

你测试脚本有这样的事情吗?

def test(): 
    pass 

if __name__ == '__main__': 
    test() 

如果不是,也许你应该将你的测试转换为调用函数,如test。然后,从您的主要测试脚本中,您可以:

import test1 
test1.test() 
import test2 
test2.test() 

提供运行测试的通用界面,以便测试自己使用。在__main__检查中有一大块代码不是一件好事。

对不起,我没有回答你问的问题,但我觉得这是正确的解决方案,没有偏离远离原来的测试代码。

+0

不幸的是没有。一些测试脚本可以实现这一点,但其他测试脚本只是将代码作为顶级模块代码。这只是一些奇怪的情况。我找出了问题并回答了我自己的问题,但感谢您的建议。我希望我能跟着它! :-) – BrenBarn 2012-07-06 07:26:10