python包内模块之间导入_2.4.1 Python 包&跨模块导入&绝对导入&相对导入

包(Package)

当你的模块文件越来越多,就需要对模块文件进行划分,比如把负责跟数据库交互的都放一个目录,把与页面交互相关的放一个目录

.

└── my_proj

├── crm#代码目录

│ ├── admin.py

│ ├── apps.py

│ ├── models.py

│ ├── tests.py

│ └── views.py

├── manage.py

└── my_proj#配置文件目录

├── settings.py

├── urls.py

└── wsgi.py

像上面这样,一个目录管理多个模块文件,这个文件夹就被称为包

不同包之间的模块互相导入

crm/views.py内容

defsayhi():print('hello world!')

通过manage.py调用

from crm importviews

views.sayhi()

执行manage.py (注意这里用python2)

Alexs-MacBook-Pro:my_proj alex$ ls

crm manage.py my_proj

Alexs-MacBook-Pro:my_proj alex$ python manage.py

Traceback (most recent call last):

File"manage.py", line 6, in

from crm importviews

ImportError: No module named crm

竟然说找不到模块,为什么呢

包就是目录,但该目录下必须存在 __init__.py 文件, 该文件的内容可以为空。__int__.py用于标识当前目录是一个包。

在crm目录下创建一个空文件__int__.py ,再执行一次就可以了

Alexs-MacBook-Pro:my_proj alex$ touch crm/__init__.py #创建一个空文件

Alexs-MacBook-Pro:my_proj alex$

Alexs-MacBook-Pro:my_proj alex$ ls crm/

__init__.py admin.py models.py views.py__pycache__apps.py tests.py views.pyc

Alexs-MacBook-Pro:my_proj alex$ python manage.py

hello world!

注意,在python3里,即使目录下没__int__.py文件也能创建成功,猜应该是解释器优化所致,但创建包还是要记得加上这个文件 吧。

跨模块导入

目录结构如下

.

├──__init__.py

├── crm

│ ├──__init__.py

│ ├── admin.py

│ ├── apps.py

│ ├── models.py

│ ├── tests.py

│ ├── views.py

├── manage.py

└── proj

├──__init__.py

├── settings.py

├── urls.py

└── wsgi.py

根据上面的结构,如何实现在crm/views.py里导入proj/settings.py模块?

直接导入的话,会报错,说找到不模块

$ python3 views.py

Traceback (most recent call last):

File"views.py", line 2, in

from proj importsettings

ModuleNotFoundError: No module named'proj'

是因为路径找不到,proj/settings.py 相当于是crm/views.py的父亲(crm)的兄弟(proj)的儿子(settings.py),settings.py算是views.py的表弟啦,在views.py里只能导入同级别兄弟模块代码,或者子级别包里的模块,根本不知道表弟表哥的存在。这可怎么办呢

答案是添加环境变量,把父亲级的路径添加到sys.path中,就可以了,这样导入 就相当于从父亲级开始找模块了。

crm/views.py中添加环境变量

importsys ,os

BASE_DIR= os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #__file__的是打印当前被执行的模块.py文件相对路径,注意是相对路径

print(BASE_DIR)

sys.path.append(BASE_DIR)from proj importsettingsdefsayhi():print('hello world!')print(settings.DATABASES)

输出

$ python3 views.py/Users/alex/Documents/work/PyProjects/luffy_课件/21天入门/chapter4-常用模块/packages/my_proj---my proj init--- #proj/__init__.py输出

in proj/settings.py #proj/settings.py输出

{'host': 'localhost'}

*注意;此时在proj/settings.py写上import urls会有问题么?

DATABASES= {

'host':'localhost'

}

import urls #这行刚加的

print('in proj/settings.py')

结果报错了

ModuleNotFoundError: No module named 'urls'

为什么呢? 因为现在的程序入口是views.py , 你在settings.py导入import urls,其实相当于在crm目录找urls.py,而不是proj目录,若想正常导入,要改成如下

DATABASES={'host':'localhost'}from proj import urls #proj这一层目录已经添加到sys.path里,可以直接找到

print('in proj/settings.py')

绝对导入&相对导入

在linux里可以通过cd ..回到上一层目录 ,cd ../.. 往上回2层,这个..就是指相对路径,在python里,导入也可以通过..

.

├──__init__.py

├── crm

│ ├──__init__.py

│ ├── admin.py

│ ├── apps.py

│ ├── models.py

│ ├── tests.py

│ ├── views.py#from ..proj import settings

├── manage.py

└── proj

├──__init__.py

├── settings.py#from .import urls

├── urls.py

└── wsgi.py

views.py里代码

from ..proj importsettingsdefsayhi():print('hello world!')print(settings.DATABASES)

执行结果报错了

Traceback (most recent call last):

File"my_proj/crm/views.py", line 4, in

from ..proj importsettings

SystemError: Parent module'' not loaded, cannot perform relative import

或者有人会看到这个错

ValueError: attempted relative import beyond top-level package

from .. import models会报错的原因是,这句代码会把manage.py所在的这一层视作package,但实际上它不是,因为package不能是顶层入口代码,若想不出错,只能把manage.py往上再移一层

正确的代码目录结构如下

packages/├──__init__.py

├── manage.py#from my_proj.crm import views

└── my_proj

├── crm

│ ├── admin.py

│ ├── apps.py

│ ├── models.py

│ ├── tests.py

│ ├── views.py#from . import models; from ..proj import settings

└── proj

├──__init__.py

├── settings.py

├── urls.py

└── wsgi.py

再执行manage.py就不会报错了。

注:虽然python支持相对导入,但对模块间的路径关系要求比较严格,处理不当就容易出错,so并不建议在项目里经常使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值