python包和模块的使用简书_Python模块和包的管理

目录

模块和包

导入包的几种方式

包内引用

自定义init.py

添加本地的包到项目中

模块和包

首先,先介绍两个概念:

模块:一个python文件(xxx.py)就是一个模块。我们可以在一个模块里定义变量、方法、类

包:模块通过包来组织和管理。从实现的方式来看,包是一个包含init.py的文件夹

导入包的几种方式

- import item.subitem.subsubitem

- from package import item (推荐使用的方式)

- from package import *

现在假设我们有下面的文件结构,michasel.py、james.py和amanda.py的代码是类似的,除了name的值不一样:

# 文件结构

school

boys

michael.py

james.py

__init__.py

girls

amanda.py

__init__.py

__init__.py

# michael.py 示例代码

name = 'Michael'

def say_hello():

print('hi, this is %s.' % (name, ))

class Info(object):

def __init__(self):

pass

def info(self):

say_hello()

默认情况下,我们不需要在init.py下添加任何代码就可以使用上述的前两种方式导入。

import item.subitem.subsubitem:使用这种方法,可以导入包或者模块,但是不能导入一个模块中定义的内容,比如模块中的类,方法或者变量等。并且引用包中的内容的时候,必须使用完整的名字(这里就是item.subitem.subsubitem)。一般使用这种方式的时候,我们可以给导入的包或者模块起别名,这样就可以避免使用很长的完整名。

import school.boys.michael

school.boys.michael.say_hello()

michael.say_hello() # NameError: name 'michael' is not defined

# 取别名

import school.boys.james as james

james.say_hello()

from package import item:从字面理解,就是从某个包中导入子包或者模块。除此之外,还可以导入某个模块中定义的类,方法或者变量等。同时,与上面那种方法相比,这种方法可以通过import后面的名字直接使用(而不需要使用完整名)。

from school.boys import james

james.say_hello()

from school.boys.michael import name

print(name)

from package import *:执行from package import * 的时候,如果init.py中定义了all列表,则会把列表中列出的模块全部导入。如果没有定义all列表,那么就不支持import *;如果定义了all却没有赋值,那么import *不会导入任何模块。

# 没有定义__all__

from school.boys import *

james.say_hello() # NameError: name 'james' is not defined

# 设置__all__ = __all__ = ['james', 'michael']

from school.boys import *

james.say_hello() # Correct

michael.say_hello() # Correct

# 设置__all__ = [](空列表)

from school.boys import *

james.say_hello() # NameError: name 'james' is not defined

包内引用

一个模块可以导入本包内的模块,也可以从邻包导入。导入的时候,可以使用相对位置或者绝对位置导入。需要注意的是,在主模块中导入不论本包或者邻包的模块的时候,总是要使用绝对位置,下面通过具体的示例来说明。

############## 引用相同包中的模块 ##############

# 在james.py中引用michael.py中定义的name

# 使用相对位置

from .michael import name as michael_name

print(michael_name)

# 使用绝对位置

from school.boys.michael import name as michael_name

################################################

############## 引用邻包中的模块 ################

# 在james.py中引用amanda.py中定义的name

# 使用相对位置

from ..girls.amanda import name as amanda_name

print(amanda_name)

# 使用绝对位置

from school.girls.amanda import name as amanda_name

################################################

############## 主模块(例如把james.py作为主模块来运行)中,必须使用绝对位置 ##############

# 例如,在james.py中以相对位置导入michael.py,并且把james.py作为主模块运行,会出现一下错误

# ModuleNotFoundError: No module named '__main__.michael'; '__main__' is not a package

from .michael import name as michael_name

print(michael_name)

#####################################################################################

自定义init.py

自动加载子模块 - 还是以本文开始的文件结构为例。现在,我们想在导入school.boys包的时候,自动就导入james.py和michael.py这两个模块。只需要在boys下的init.py中添加下面的代码

# school/boys/__init__.py

from . import james

from . import michael

# 在主模块中导入

import school.boys

school.boys.michael.say_hello()

合并子模块为单一的逻辑模块 - 例如james.py下有james_greeting方法,michael.py下有michael_greeting方法,希望在主模块中调用的时候,看起来这两个方法属于同一个模块,比如属于boys这个包,这样就不需要导入michael.py、james.py

# school/boys/__init__.py

from .james import james_greeting

from .michael import michael_greeting

# 在主模块中导入

import school.boys

school.boys.michael_greeting()

school.boys.james_greeting()

包命名空间 - 文章一开始的部分就提到,我们可以在一个模块中导入一个包,一个包下面包含init.py文件。如果你好奇,或许你已经试过了 - 如果我们删除了包下面的init.py,我们依然可以在模块中导入这个包,这个神奇的魔法是通过“包命名空间”实现。当一个文件夹下不包含init.py的时候,那么解释器将把这个文件夹理解为包命名空间。这种用法,可能会用在一些开发框架中,对于框架的使用者而言,可以创建相同名称的文件夹并创建自己的模块,相当于把自己的模块整合到该开发框架中。我们可以输出某个包的str,通过判断是否包含"namespace"来判断是否是包命名空间。

import school.boys

print(school.boys.__path__)

print(school.boys)

# output

# 包

['D:\\Workspace\\Python\\PackageDemo\\school\\boys']

# 包命名空间

_NamespacePath(['D:\\Workspace\\Python\\PackageDemo\\school\\boys'])

添加本地的包到项目中

有一种情况是,在公司的项目中,我们需要使用到一些自家的通用的包,这个包无法通过网络获取,但是在我们的开发环境中可以找到,那在我们开发的项目中,如何去导入呢?一种简单粗暴的方法是,将包所在的路径添加的系统变量PATHONPATH中(其实还可以pip install --user packagename 来安装私有包);另一个种是我们在项目中,修改sys.path,这样去告诉解释器去哪里找这个包。例如,现在我们把这个自家是包复制到项目是packages目录中:

import sys

from os.path import abspath, join, dirname

sys.path.insert(0, join(abspath(dirname(__file__)), 'src'))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值