第10章 模块和包

本文详细介绍了Python中包和模块的管理,包括如何通过__init__.py创建包,如何导入模块,以及如何处理导入错误。重点讨论了sys.path的使用,如何修改它来添加包的路径,以及通过环境变量持久化设置。同时,文章还讲解了模块中的__all__属性,用于控制from...import*的行为。
摘要由CSDN通过智能技术生成

简介

  • 包:将 多个功能模块 放在 一个包含__init__.py的文件夹里 , 对 不同功能的模块 进行分组管理。包可以嵌套定义。
  • 模块:一个封装 具有相似功能的多个函数 的Python文件。

(在PyCharm中,创建普通文件夹并在其中创建__init__.py,普通文件夹将自动转换标记为package,和直接创建package结果相同)

导入

# from和import之后...代表 包名/模块名/属性名/方法名/类名
# as之后...代表 别名
import ...
import ... as ...
from ... import ...
from ... import ... as ...

导入包后,python解释器会找到包并执行其中的部分代码。在sys.path中可以看到python解释器会查找的路径。若导入包后提示没有找到包或包不存在,可以执行其中一个操作:1)将包放在正确的位置;2)告诉解释器到哪里去找包;

方便理解,这里举一个例子:
phello: 包
__init__.py 创建包时的默认文件
mhello.py 模块

# mhello.py
def printHello():
    print('Hello World!')

1)将包放在正确的位置

sys.path包含一个目录列表,解释器将在这些目录中查找包。

其中较常用的为“site-packages目录”和“当前项目目录”。其中site-packages为默认的包安装位置,pip install和conda install的包都将存放在site-packages目录下;当前项目目录指的是用户个人正在编写的项目位置,在PyCharm中创建的包一般放在当前项目目录(或更下级目录)中,简单直观,方便编写和调试。

site-packages目录:不要放置单个py文件(例如mhello.py),而是放置包含py文件的包/文件夹(例如phello)
当前项目目录:可以放置单个py文件(例如mhello.py)

# 打印sys.path内容查看搜索路径

# windows
>>> import sys
>>> print(sys.path)
['E:\\PyCharm 2021.3\\plugins\\python\\helpers\\pydev', 
'E:\\PyCharm 2021.3\\plugins\\python\\helpers\\pycharm_display',
'E:\\PyCharm 2021.3\\plugins\\python\\helpers\\third_party\\thriftpy', 
'E:\\PyCharm 2021.3\\plugins\\python\\helpers\\pydev', 
'E:\\anaconda\\envs\\py37tfcpu\\python37.zip', 
'E:\\anaconda\\envs\\py37tfcpu\\DLLs', 
'E:\\anaconda\\envs\\py37tfcpu\\lib',
'E:\\anaconda\\envs\\py37tfcpu', 
 # site-packages目录
'E:\\anaconda\\envs\\py37tfcpu\\lib\\site-packages',
'E:\\PyCharm 2021.3\\plugins\\python\\helpers\\pycharm_matplotlib_backend',
 # 当前项目目录
'C:\\Users\\shang\\Desktop\\pythonProject', 
'C:/Users/shang/Desktop/pythonProject']

# linux
>>> import sys
>>> print(sys.path)
[
# 当前项目目录
'', 
'/root/miniconda3/envs/moviedeal/lib/python37.zip',
'/root/miniconda3/envs/moviedeal/lib/python3.7',
'/root/miniconda3/envs/moviedeal/lib/python3.7/lib-dynload',
 # site-packages目录
'/root/miniconda3/envs/moviedeal/lib/python3.7/site-packages']

windows例:

# 将phello包放到main.py同级目录

# main.py
from phello.mhello import printHello

printHello()
# 将mhello.py模块放到main.py同级目录

# main.py
from mhello import printHello

printHello()
# 将phello包放到'E:\\anaconda\\envs\\py37tfcpu\\lib\\site-packages'目录中

# main.py
from phello.mhello import printHello

printHello()

linux例:

# 将phello包放到main.py同级目录

# main.py
from phello.mhello import printHello

printHello()
# 将mhello.py模块放到main.py同级目录

# main.py
from mhello import printHello

printHello()
# 将phello包放到'/root/miniconda3/envs/moviedeal/lib/python3.7/site-packages'目录中

# main.py
from phello.mhello import printHello

printHello()

2)告诉解释器到哪里去找

i)直接修改sys.path(不常见)

仅修改运行此次运行的sys.path

windows
# 将phello包放到main.py同级目录放在D盘根目录则sys.path.append('D:')
# 将phello包放到main.py同级目录放在D:/pkg录则sys.path.append('D:/pkg')

# main.py
import sys
sys.path.append('D:/pkg')

from phello.mhello import printHello

printHello()
linux

将phello包放到’~'目录下

不能直接将’‘添加到sys.path的末尾,必须使用完整的路径(例如’/home/yourusername’)或自动创建完整的路径(os.path.expanduser(''))

# main.py
import sys
sys.path.append('/home/yourusername')

from phello.mhello import printHello

printHello()
# main.py
import sys
import os
sys.path.append(os.path.expanduser('~'))

from phello.mhello import printHello

printHello()

ii)添加环境变量(标准做法

关于环境变量详细参考:windows和linux的环境变量

pycharm会占用PYTHONPATH变量,使得在系统中配置的PYTHONPATH失效,所以分为使用cmd和使用pycharm运行main.py

windows

将phello包放到’D:\pkg’目录下

使用cmd

添加环境变量

image-20220803223856461

# main.py
from phello.mhello import printHello

printHello()
使用pycharm

在pycharm的解释器上添加临时环境变量

image-20220803225031665

image-20220803225106748

# main.py
from phello.mhello import printHello

printHello()
linux

将phello包放到’~'目录下

使用cmd
> vim ~/.bashrc
# 在后面插入一行
# export PYTHONPATH=$PYTHONPATH:~
> source ~/.bashrc
# 命令行执行,不要使用pycharm(pycharm会占用PYTHONPATH变量,使得在系统中配置的PYTHONPATH失效)

# main.py
from phello.mhello import printHello

printHello()
使用pycharm

同windows,在pycharm的解释器上添加临时环境变量

编写

模块

注意__all__的使用:__all__为 from … import * 后外部所能导入属性,方法、类等,直接使用"模块名.xxx"或导入时指定"属性,方法,类"则不受影响。即__all__内容为该模块的主观开放成员(属性、方法、类等),所谓主观开放即作者主观上允许其他人调用的,而不在__all__中的内容作者不希望其他人调用(但是python语言的机制不是强制的,直接使用"模块名.xxx"或导入时指定"属性,方法,类"仍然可以调用)。

  1. 新建py文件test.py
  2. 编写模块
# test.py
__all__=['t1', 'printHello']

t1 = 2

t2 = 3


def printHello():
    print('Hello')


def printWorld():
    print('world')
  1. 导入和调用测试
# 成功调用t1, t2, printHello, printWorld
import test
print(test.t1)
print(test.t2)
test.printHello()
test.printWorld()
# 2
# 3
# Hello
# world

# 成功调用t1, t2, printHello, printWorld
from test import t1, t2, printHello, printWorld
print(t1)
print(t2)
printHello()
printWorld()
# 2
# 3
# Hello
# world

# 成功调用t1, printHello
# t2, printWorld不存在
from test import *
print(t1)
printHello()
# 2
# Hello

# digithello.py

__all__ = ['hello1', 'hello2']


def hello1():
    print('Hello 1')


def hello2():
    print('Hello 2')


def selfhello3():
    print('Self Hello 3')
    
    
# letterhello.py

__all__ = ['helloA', 'helloB']


def helloA():
    print('Hello A')


def helloB():
    print('Hello B')


def selfhelloC():
    print('Self Hello C')

空init

# __init__.py为空


# main.py

from hello.digithello import *
from hello.letterhello import *

hello1()
hello2()
helloA()
helloB()

非空init

使用__init__.py的优点:
1) 在__init__.py按需批量import,可以简化调用该包时的import语句
2) 在__init__.py按需import 搭配 新的__all__,定义 综合包内各个模块的总主观开放成员

# __init__.py

# 模块名可以使用hello.xxx或.xxx,不能使用xxx
from hello.digithello import *
from hello.letterhello import selfhelloC

__all__ = []
# 此处只能使用xxx.__all__,不能使用.xxx.__all__或hello.xxx.__all__
__all__.extend(digithello.__all__)
__all__.append('selfhelloC')


# main.py
from hello import *

hello1()
hello2()
selfhelloC()

__,定义 综合包内各个模块的总主观开放**成员

# __init__.py

# 模块名可以使用hello.xxx或.xxx,不能使用xxx
from hello.digithello import *
from hello.letterhello import selfhelloC

__all__ = []
# 此处只能使用xxx.__all__,不能使用.xxx.__all__或hello.xxx.__all__
__all__.extend(digithello.__all__)
__all__.append('selfhelloC')


# main.py
from hello import *

hello1()
hello2()
selfhelloC()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MallocLu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值