python import 机制初探

系统 1656 0

引子

考虑有如下代码结构

          
            .
├── cat
│   ├── __init__.py
│   ├── cat.py
│   └── moo.py
└── dog
    ├── __init__.py
    └── dog.py

2 directories, 5 files
          
        

情况1:

          
            # ./cat/cat.py
import moo
          
        

其余文件为空。如果我们用运行命令: python cat/cat.py ,则程序正常运行;如果运行命令; python -m cat.cat ,则会报错;

情况2:

          
            # ./cat/cat.py
from . import moo
          
        

则运行结果相反。

其实,我们的问题早就有人提出过了。PEP 395

The fact that most methods of invoking Python code from the command line break when that code is inside a package, and the two that do work are highly sensitive to the current working directory is all thoroughly confusing for a beginner. :如果一段代码在一个包内,那么从命令行使用这段代码是非常非常容易出错的,只有2种方法可行:
  1. 在整个包的外部, python -c "from module import code
  2. 在整个包的外部,通过 -m 参数执行。

如果在包内部,即使你的代码正确,也基本会出错。

分析

情况1:

  • 当我们运行 python cat/cat.py 时,这时候系统的搜素路径包括 ./cat/ ,我们可以通过在 ./cat/cat.py 中添加 import sys; print(sys.path) 证实这一点。
  • 当我们运行 python -m cat.cat 时,系统的搜索路径只包括 . ,也就是当前文件夹,我们可以通过在当前文件夹下添加一个 moo.py 文件,这样 python -m cat.cat 就不会报错了。可见,这时的搜索空间,不包括自文件夹。

情况2:

情况2其实和情况1很不一样,情况2叫做 package relative import ,也就是包内间接引用。顾名思义,这种引用方法 只能在包内使用 。也就是说,只能通过 python -m cat.cat , 或者是 python -c "from cat import cat" 之类的方法来使用。以下内容源自 python 官方文档中的 The import statement

When a module or package is contained within another package ... using leading dots in the specified module or package after from you can specify how high to traverse up the current package hierarchy without specifying exact names.

官方文档中的Package Relative Import 展示了详细的用法。

import

python 中,载入一个包有几种方式:

  1. import 语句
  2. importlib 模块提供的方法
  3. 内置方法 __import__ (不提倡)

python 中,有 module ,有 package package 都是 module , 但 module 不一定是 package module 只有一种, package 有2种。

代码重载: importlib.reload

使用 importlib.reload 会重载当前代码。

          
            import os
import importlib

import foo
print("foo.a: {}".format(foo.a))

command = 'echo a=2 >> foo.py'

print(command)
os.popen(command)

importlib.reload(foo)
print("foo.a: {}".format(foo.a))
          
        

输出:

          
            foo.a: 2
echo a=2 >> foo.py
foo.a: 2
          
        

参考资料

import 语法

PEP 395

PEP 420


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论