首页后端开发PHPPython中的模块系统(python 系统模块)

Python中的模块系统(python 系统模块)

时间2023-04-03 16:56:01发布访客分类PHP浏览1529
导读:模块随着程序功能越来越复杂,代码量也急剧增加。可以通过将逻辑相近的代码分割到不同的文件中,减少单个文件中代码的行数,提高可维护性。在Python中一个py文件就是一个模块,一个大型的代码项目,一般是由多个文件(模块)组成。一个模块可以被另一...


模块


随着程序功能越来越复杂,代码量也急剧增加。可以通过将逻辑相近的代码分割到不同的文件中,减少单个文件中代码的行数,提高可维护性。在Python中一个py文件就是一个模块,一个大型的代码项目,一般是由多个文件(模块)组成。一个模块可以被另一个模块导入使用。

在Python中,包含__init__.py文件的目录被称为包,包被用来声明模块之间的查找关系。比如下面的app就是一个包,test也是一个包。app可以被看做是test的子包。

test
├── app
│   ├── config.py
│   ├── __init__.py
│   └── lib.py
├── __init__.py
└── main.py


__init__.py文件可以为空。__init__.py文件中一般用来导出所在目录下的其他模块。
当目录中不存在__init__.py文件时,该目录也可以被称为一个包,只是习惯上喜欢在每个目录中放置一个__init__.py文件。至于两者区别,含有__init__.py的目录,可以讲__init__.py看做一扇可以通往该目录下所有模块的大门,


导入方法


在Python中导入一个包或模块时,有两种主要的方法,一种是使用import关键字进行导入,另一种是使用官方库importlib来进行导入,后者常被用于一些需要自定义导入的,或者是自动导入某些模块的场景下。


导入一个模块

app
├── config.py
├── __init__.py
└── lib.py


lib.py导入config.py时,可以直接通过import进行导入

# lib.py
import config


导入一个包

test
├── app
│   ├── config.py
│   ├── __init__.py
│   └── lib.py
├── __init__.py
└── main.py


main.py中导入app包时,可以直接使用import进行导入

# main.py
import app


与导入模块不同,导入一个包时,包目录下的__init__.py文件会被自动执行。


导入包中的某一个具体模块时

import app.lib


那么导入一个包可以认为是通过下面这种方式进行导入的,只是在Python中可以将这种方式简写为imoprt app

import app.__init__ as app


as


在导入时,Python会将当前导入的包或模块自动添加到全局变量空间中,有时可能会出现下面这种情况

import lib1.app
import lib2.app


在不同的包中,存在名字相同的模块,这是后者就会将前者覆盖,通过as可以将导入的变量重命名。

import lib1.app as app1
import lib2.app as app2


使用相对路径进行导入


当代码项目过大时,文件关系复杂或者模块的嵌套层级过深时,可以通过相对导入的方式进行导入某一个模块

test
├── app
│   ├── config.py
│   ├── __init__.py
│   ├── lib.py
│   └── __pycache__
│       └── __init__.cpython-39.pyc
├── auth
│   ├── config.py
│   └── __init__.py
├── __init__.py
└── main.py


app/lib.py文件需要使用auth/config.py模块的功能时,可以这样进行导入

# app/lib.py
from ..auth import config as auth_config


这种导入方法必须是使用from进行导入,包前面一个点表示同一目录,两个点表示上一级目录,三个点表示上一级目录的上一级目录,以此类推。
在使用这种方法时,对于新手经常会出现下面这种报错

ImportError: attempted relative import with no known parent package


出现这种原因是因为,在使用相对导入时,必须存在一个最上层位置,在Python中,使用python main.py运行main.py文件,则main.py所在的目录即为最上层位置,其他的则为下层位置。当python test/app/lib.py时,最上层位置变成了test/app,所以此时..auth自然无法找到。解决方法是,在使用相对路径导入时,要明确最后运行文件的所在目录,来确定最上层位置,如果你确定不了,那就最好不要使用。


循环导入


当一个项目的模块数量很多时,可能模块之间的依赖关系错综复杂,会出现A导入B,而B也导入了A,从而构成了循环导入的情况。

# A.py
import B
print(B.b)
a = 1
# B.py
import A
print(A.a)
b = 1
python A.py
AttributeError: partially initialized module 'B' has no attribute 'b' (most likely due to a circular import)


出现循环引用问题,绝大多数情况都是因为人为设计失误造成的,你可以通过引入新模块,减少A和B相互依赖的变量。


importlib


在使用import关键字导入模块时,会调用内置的__import__方法,通过importlib可以绕过__import__方法,实现自己的导入模块的逻辑,比如在导入前做一些初始化工作,或者是进行自动导入的逻辑。

test
├── app
│   ├── config.py
│   ├── __init__.py
│   ├── lib.py
│   └── __pycache__
│       └── __init__.cpython-39.pyc
├── auth
│   ├── config.py
│   └── __init__.py
├── __init__.py
└── main.py


from importlib import import_module
app_config = import_module('app.config')


需要注意的是,在使用这种方式在导入一个包下面的模块时,__init__.py也会自动被调用。


一些常见的import写法

from app import config as app_config
import app.config as app_config
# import * 表示导入所有的模块
from app import * as app_all


Python是如何进行查找路径的


在Python中,import通过sys.path下面的路径进行查找要导入的包或模块。Python首先会先从当前目录中查找模块,找不到会继续从sys.path下面进行查找,最后找不到会抛出错误。
可以通过修改sys.path来修改查找的顺序,比如下面这样

test
├── app
│   ├── config.py
│   ├── __init__.py
│   ├── lib.py
│   └── __pycache__
│       └── __init__.cpython-39.pyc
├── auth
│   ├── config.py
│   └── __init__.py
├── __init__.py
└── main.py
# test/app/config.py
apple = 'apple'
# test/main.py
import sys
sys.path.append('./app')
import config
print(config.apple)  # apple


资料引用


https://docs.python.org/zh-cn/3/reference/import.html#
https://docs.python.org/zh-cn/3/library/importlib.html#
https://docs.python.org/zh-cn/3/tutorial/modules.html#

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

Python

若转载请注明出处: Python中的模块系统(python 系统模块)
本文地址: https://pptw.com/jishu/933.html
Python3,我只用了10行代码,就写了一个词云生成器.(python生成词云的代码) Python3,为了无损压缩gif动图,我不得不写了一个压缩神器,真香.(python gif压缩)

游客 回复需填写必要信息