【问题标题】:How to know if python script was run using interpreter's -m option?如何知道 python 脚本是否使用解释器的 -m 选项运行?
【发布时间】:2012-01-11 00:48:30
【问题描述】:

阅读完以下所有内容后我找不到答案:

理由:
当使用相对导入的测试脚本在没有-m 选项的情况下运行时,我可以打印一条警告消息,而不是给用户留下导致ValueError: Attempted relative import in non-package 异常的标准回溯。在不知道这一点的情况下,我可以捕捉到这个异常,只有 suggest 缺少 -m 选项可能是错误的原因。

【问题讨论】:

  • 你需要它做什么?你能举一些例子或测试用例来说明这种需求吗?

标签: python command-line


【解决方案1】:

免责声明:这只是一个观察,我没有在文档中看到它,因此它可能依赖于实现,并且在不同的 Python 版本之间可能不一致。

我注意到,当使用-m 选项调用脚本时,名为__loader__ 的变量会添加到命名空间中,因此您可以在脚本顶部检查该变量是否存在:

if '__loader__' in globals():
    # called with -m

为了更加安全,您可以检查__loader__ 是否是pkgutil.ImpLoader 的实例:

if '__loader__' in globals() and __loader__.__class__.__name__ == 'ImpLoader':

【讨论】:

  • 这个runpy模块的文档中; 在执行模块代码之前,在全局字典中设置了特殊的全局变量__name____file____loader____package__(请注意,这是最小的变量集 - 可以设置其他变量隐含地作为解释器实现细节)。 但是__loader__ 是一种通用的,我们永远不知道有一天还有什么可以设置它......
  • @RaymondHettinger 在这种情况下是否有任何理由没有设置真正的唯一全局变量?
  • 唯一保证唯一的变量是 None 和 __debug__;但是,任何双下划线名称都被视为保留供核心开发人员创建,因此 __loader__ 在某种程度上是安全的(或至少与 __name__=='__main__' 一样安全)。如果它让您彻夜难眠,则始终可以自省对象以验证匹配。
  • 我很好奇你为什么不使用isinstance
  • @PiotrDobrogost - pkgutil.ImpLoader 不是命名空间的一部分,需要先导入。这是另一种选择。
【解决方案2】:

另一个观察是__package__在直接执行脚本时设置为None,在使用-m时设置为包名(当模块不包含在任何包中时使用空字符串,所以它仍然不同于None)。

【讨论】:

猜你喜欢
  • 2012-08-11
  • 2010-11-29
  • 2016-01-17
  • 2013-02-10
  • 2012-03-09
  • 2013-01-01
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
相关资源
最近更新 更多