我无法弄清楚导入系统。为什么当我这样做时:
import os.path
然后我可以访问os.walk
,它位于os
,虽然我没有明确导入os
?出于某种原因,这样的假动作不适用于它的package 。这是由于什么原因造成的?
更新
我知道 import 将导入的内容带入模块的命名空间。所以定义模块'myutils.py'c
import requests
在另一个模块中,得到如下图
import myutils
resp=myutils.requests.get('http://ya.ru') # работает
resp2=requests.get('http://ya.ru') # NameError: name 'requests' is not defined
os.path 中的 import os 机制是否有一些特殊性?我知道 os.path 是 os 的一部分,而不是 2 个完全独立的包,但我想确切地了解该机制。
在 Python 中导入结合了两个操作:
=
)在搜索阶段(第 1 项)- 从规范-
import
构造:也就是说,
import a.b.c
导入 modulesa
,a.b
,a.b.c
如果上述任何模块导入失败,则无法成功导入更嵌套的模块。在命名阶段(第 2 项):
import a.b.c
在 Python 中,使a
当前命名空间中的名称可用(例如,导入模块的全局命名空间a.b.c
)并将属性:a.b
和属性属性:分配a.b.c
给适当的加载模块(类似于:a = sys.modules['a']
;;a.b = sys.modules['a.b']
..)。尽管这个问题很棘手,因为它
os
不是 Python 包(__path__
属性未设置)并且os.path
是普通属性(与 相同os.walk
),不同之处在于它os.path
是一个模块并且os.py
包含 hack:(sys.modules['os.path'] = path
允许import os.path
构造)。import os
本身已经可以os.path
在没有import os.path
.使用更常规的示例改写问题:
import html.parser
导入html
和 (自然地)html.parser
模块,并且由于html/__init__.py
(在导入步骤中执行html
)定义escape
了一个函数,它html.escape()
也可以像我们刚刚执行的那样使用import html
。如果
module.name
afterimport module
不起作用,那么这意味着您module/__init__.py
没有定义name
.旁白:性能
module.name
不依赖于__all__
.__all__
公开名称的文档(正式名称可由 访问from module import *
)以避免在不属于接口的每个名称前加上_
(默认情况下类型名称从 中_name
排除from module import *
)。但这并不禁止显式引用如module._name
(这应该避免,但如果你真的想要,你可以)。旁白:不要from module import *
在 REPL 之外或__init__.py
文件之外使用(合理使用示例:asyncio/__init__.py
-asyncio
提供“平面”公共接口(名称可直接用作asyncio.name
),尽管实现分布在许多嵌套模块中) .只有显式导入才能导入
mypackage.mymodule_XXX
和使用。mypackage.mymodule_YYY
__init__.py
mymodule_YYY
假设您有一个包裹
mypackage
:__init__.py:
然后你可以在你的程序中做你想做的事:
至于
myutils
。当您导入一个模块时,您只是将一个变量引入程序的命名空间,而不是引入一个myutils
变量,因此它没有被定义是合乎逻辑的。requests
一个变量myutils
,它是一个模块,有自己的命名空间,有一个变量requests
,所以myutils.requests
你可以通过它访问它。当您导入 os.path 时,实际上导入了 os,显然 os 只是请求路径属性,这些导入不再发生
从 os 导入路径将是正确的