当前位置: 首页 > 面试题库 >

为什么Python的import语句的from形式绑定模​​块名称?

尉迟鸿熙
2023-03-14
问题内容

我有一个具有以下结构的Python项目:

testapp/
├── __init__.py
├── api
│   ├── __init__.py
│   └── utils.py
└── utils.py

testapp/api/__init__.py具有以下代码的模块外,所有模块均为空:

from testapp import utils

print "a", utils

from testapp.api.utils import x

print "b", utils

并且testapp/api/utils.py定义x

x = 1

现在我从根导入testapp.api

$ export PYTHONPATH=$PYTHONPATH:.
$ python -c "import testapp.api"
a <module 'testapp.utils' from 'testapp/utils.pyc'>
b <module 'testapp.api.utils' from 'testapp/api/utils.pyc'>

导入的结果使我感到惊讶,因为它表明第二条import语句已被覆盖utils。但是文档指出from语句不会绑定模块名称:

从形式不绑定模块名称:它遍历标识符列表,在步骤(1)中找到的模块中查找每个标识符,然后将本地名称空间中的名称绑定到由此找到的对象。

实际上,在终端中使用from ... import ...语句时,不会引入任何模块名称:

>>> from os.path import abspath
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined

我怀疑这与Python有关,在第二个import语句时,尝试导入testapp.api.utils引用testapp.utils并失败,但是我不确定。

这是怎么回事


问题答案:

从导入系统文档中:

当使用任何机制(例如importlibAPI,import或, import-from
语句或内置__import__())加载子模块时,将在父模块的名称空间中放置与子模块对象的绑定。例如,如果packagespam具有一个子模块foo,则在导入后spam.foospam将具有foo绑定到该子模块的属性。假设您具有以下目录结构:

spam/
    __init__.py
    foo.py
    bar.py

spam/__init__.py包含以下几行:

from .foo import Foo
from .bar import Bar

然后执行以下命令,将名称绑定到foobar放在spam模块中:

>>> import spam
>>> spam.foo
<module 'spam.foo' from '/tmp/imports/spam/foo.py'>
>>> spam.bar
<module 'spam.bar' from '/tmp/imports/spam/bar.py'>

鉴于Python熟悉的名称绑定规则,这似乎令人惊讶,但这实际上是导入系统的基本功能。不变的条件是,如果您有sys.modules['spam']and
sys.modules['spam.foo'](如在上述导入之后一样),则后者必须作为foo前者的属性出现。

如果这样做from testapp.api.utils import x,import语句将不会加载utils到本地名称空间中。但是,导入机制

加载utilstestapp.api名称空间中,以使进一步的导入工作正常。碰巧您的情况testapp.api也是本地名称空间,所以您会感到惊讶。



 类似资料:
  • 如果你想要直接输入argv变量到你的程序中(避免在每次使用它时打sys.),那么你可以使用from sys import argv语句。如果你想要输入所有sys模块使用的名字,那么你可以使用from sys import *语句。这对于所有模块都适用。一般说来,应该避免使用from..import而使用import语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。

  • 问题内容: 该蟒蛇风格指南建议对进口组这样的: 导入应按以下顺序分组: 标准库导入 相关第三方进口 本地应用程序/特定于库的导入 但是,它没有提及应如何布置两种不同的进口方式的内容: 对它们进行排序有多种方法(假设所有这些导入都属于同一组): 首先,然后 from x import xx import abc import def import x 首先,然后 import def import

  • 问题内容: 我有问题要覆盖使用from … import语句的方法。一些例子来说明这个问题: 我想重写print_message(msg)方法而不更改a或b模块中的代码。我尝试了很多方法,但是从… import导入了原始方法。当我将代码更改为 比我看到的改变。 你能建议我如何解决这个问题吗? 预先感谢您的任何小例子。 最好的祝福 ------------------更新--------------

  • 我正在使用NextJS与typescript,mongo Atlas,mongoose,node和Express。 当我运行node Pages/Server时,我收到以下错误:我已经上载了我的package.json文件,并且还添加了babel 从“express”导入express;^^^^^^ SyntaxError:不能在模块外部使用导入语句,位于wrapSafe(内部/modules/c

  • 本文向大家介绍Python import自定义模块方法,包括了Python import自定义模块方法的使用技巧和注意事项,需要的朋友参考一下 python包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的路径。 下面将具体介绍几种常用情况: (1)主程序与模块程序在同一目录下: 如下面程序结构:     若在程序test1.py中导入模块mod1, 则直接使用im

  • 5.2. 使用 from module import 导入模块 Python 有两种导入模块的方法。两种都有用,你应该知道什么时候使用哪一种方法。一种方法, import module,你已经在第 2.4 节 “万物皆对象”看过了。另一种方法完成同样的事情,但是它与第一种有着细微但重要的区别。 下面是 from module import 的基本语法: from UserDict import