【问题标题】:Running python package sub-module independently for self-test; import path kludge独立运行python包子模块进行自检;导入路径组合
【发布时间】:2020-03-06 03:26:35
【问题描述】:

我经常在模块底部写自测代码,即

if __name__ == '__main__':

.
.
.

我想把它保留在模块中,这样如果我修改它,我仍然可以在它上面运行自检。该模块是包的一部分。所以有包间引用需要解决;但是如果我是导入包而不是独立运行模块,这些解决方法会有所不同。

我最终在我的模块顶部有一个这样的杂物,这肯定是丑陋的,可能不是“pythonic”:

if __name__ == '__main__':

    from CovSample import CovSample
    from ArrayByRow import ArrayByRow    
else:

    from CEOpt import CovSample
    from CEOpt import ArrayByRow

这有效 - 如果我正在导入包 CEOpt - else-branch 引用有效,如果我正在独立运行 - 直接模块名称导入有效。但这并不漂亮我想要一个仍然在独立模块测试中工作的包间调用的导入语句。这可能吗?

【问题讨论】:

  • 请注意,进行 within-package 导入的更好方法是相对地执行它们(即不必显式命名CEOpt)并使用前缀点使相对性显式:from .CovSample import CovSamplefrom .ArrayByRow import ArrayByRow。但是,__name__=='__main__' 也不起作用,因此它不能回答您的问题。我也很想知道是否有通用的方法。

标签: python


【解决方案1】:

It seems 没有通用的方法可以在两种情况下都起作用,__name__=='__main__'__name__!='__main__'

我所做的如下:在每个子模块中定义一个Test() 函数(所以CEOpt.CovSample.Test()CEOpt.ArrayByRow.Test())。然后创建一个CEOpt/__main__.py 文件,这是CEOpt 包中唯一一个您将直接“运行”的文件(该特定文件名确保它是当您从shell 中说python -m CEOpt 时运行的文件)。该文件必须通过名称明确地import CEOpt,但至少现在只需要在一个地方发生(其他文件可以使用带有前缀点语法的相对导入,例如from .CovArray import CovArray)。现在编写__main__.py 的逻辑,使其响应通过sys.argv 传入的子命令,选择运行哪个子模块的Test() 函数。

例如,语法python -m CEOpt test CovArray(或等效地来自IPython提示符的%run CEOpt/__main__ test CovArray)将触发__main__.py调用CEOpt.CovArray.Test()

【讨论】:

  • 谢谢 - 这是一个好方法。就我而言 - 我通常开发一个模块,然后决定我希望它存在于一个包中。所以我有几周或几个月的时间,模块必须在没有包开销的情况下运行——然后我把它放在包中。如果我从一开始就知道我正在制作一个包裹,那么你的方法对我有用。我可能不得不忍受我的笨拙或开始计划我的工作!
  • 也许您仍然可以从一开始就将测试代码放在Test() 中,但要养成使用import thing; thing.Test() 而不是run thing 的习惯。或者,您可以创建自己的 IPython 魔术 %runtest,在命名目标(子)模块上执行 importlib.reload(importlib.import_module(targetModuleName)).Test()。然后你只需要输入%runtest CovArray——或者,在你的开发后期,%runtest CEOpt.CovArray
猜你喜欢
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多