【问题标题】:module imported by top level script not seen by custom modules自定义模块看不到由顶级脚本导入的模块
【发布时间】:2017-07-31 14:52:17
【问题描述】:

我有一个顶级脚本(在顶级目录中)导入自定义模块“报告”(在子目录中)

当脚本从使用 re.match 的模块调用函数时,我遇到了导入问题,当我启动它时出现错误:

    111         if sys.argv[i] in valid_options:
    112             current_option_type = valid_options[sys.argv[i]];
--> 113             if (re.match(r'\barg\b',current_option_type)):

'NameError: name 're' is not defined'`

确实,当我检查导入的模块时,我最终得到了

In [12]: set(sys.modules)&set(globals()) Out[12]: {'datetime', 'os', 'sys'}

为了使其工作,我决定导入另一个模块,该模块本身导入 re(并且位于子目录中):

import ip_interface

我调用我的函数并以同样的错误结束,当我检查时,我有:

In [14]: set(sys.modules)&set(globals()) Out[14]: {'datetime', 'ip_interface', 'os', 'sys'}

所以我改变了导入 ip_interface 模块的方式并执行以下操作:

from ip_interface.ip_interface import *

我检查了我导入的模块:

In [16]: set(sys.modules)&set(globals()) Out[16]: {'datetime', 'ip_interface', 'knxnet', 'os', 're', ===> I got it ! 'socket', 'subprocess', 'sys'}

然后我启动我的脚本并最终得到:

    111         if sys.argv[i] in valid_options:
    112             current_option_type = valid_options[sys.argv[i]];
--> 113             if (re.match(r'\barg\b',current_option_type)):

NameError: name 're' 未定义

我想知道有什么问题,因为我可以看到导入的“re”模块。

当我直接在我的模块中导入它时,它终于可以工作了。 是否可以“共享”导入并避免在所有需要它的子模块中执行?

【问题讨论】:

  • 理论上应该可行。为什么你这样做 from ip_interface.ip_interface import * 而不是 from ip_interface import *?
  • 我有一个名为 ip_interface 的包,其中包含 ip_interface.py

标签: python import module


【解决方案1】:

为了避免NameError,你必须在你的主模块中使用import re,否则re 的名称将在那里不为人知。在导入的模块中执行 import re 是不够的,因为那是不同的命名空间。

它出现在sys.modules 中的事实仅意味着它已被导入到某个地方。但是要在模块的命名空间中看到它,您需要在该模块中执行import re

【讨论】:

  • 这很奇怪。我已经用一个 dummy.py 进行了测试,它 import re: In [1]: from dummy import * In [2]: import sys In [3]: set(sys.modules)&set(globals()) Out[3]: {'内置', 're', 'sys'}
  • from dummy import * 从您的命名空间中的 dummy 导入每个名称。在dummy 中导入的re 模块也是如此。
  • 顺便说一句,通常不建议使用from xxx import *,因为您使用xxx 中定义的所有名称污染了自己的命名空间。
  • 我在我的顶级模块中执行以下导入:import re、from ip_interface.ip_interface import * 和 from reporting.reporting import *,我启动了一个新的 python shell(可以肯定)但它给了我相同的消息...是否有可能知道为命名空间加载了哪些模块?
  • 也许吧。我不得不考虑一下。但我认为这是一个红鲱鱼。要遵循的规则是:如果您使用像 x.y 这样的构造,您需要确保 x 在您的 current 命名空间中是已知的。如果x 是标准库中的一个模块,那么执行此操作的规范方法是import x
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-20
  • 1970-01-01
  • 1970-01-01
  • 2021-02-05
相关资源
最近更新 更多