Python模块学习:导入模块和package

模块:用来从逻辑上组织python代码(变量,函数,类),本质上就是以.py结尾的python文件
package:本质上就是一个目录,但是必须带一个init.py的文件,它是用来从逻辑上组织模块的

import的本质是什么?
导入模块的本质:就是把python文件拿来解释一遍
导入包的本质:就是执行该package下的init.py文件、

基础知识
当你import的时候,python只会在sys.path这个变量(一个list,你可以print出来看)里面的路径中找可能匹配的package和module。

而一个package跟一个普通文件夹的区别在于,package的文件夹中多了一个__init__.py文件。换句话说,如果你在某个文件夹中添加了一个__init__.py文件,则python就认为这个文件夹是一个package。

init.py文件可以是空的(也推荐者这么做),它只是告诉python当前文件夹是一个package。当然,也可以在里面添加一些代码,这些代码会在import这个包的时候运行。

所以,请确保你要import的文件所在的文件夹有__init__.py文件(除非它在sys.path中某个文件夹下)。

导入模块

如果我现在有一个这样的目录:
在这里插入图片描述
在bin文件目录下的hello.py内容是:

def hello():
    print('i am in bin dir')

在Day5文件目录下的hello.py内容是:

def hello():
    print('i am in Day5 dir')

在pythonFile文件目录下的hello.py内容是:

def hello():
    print('i am in pythonFile dir')

如果我现在在bin目录下的test.py下写入

import hello
hello.hello()

会出现的结果是什么呢?

i am in bin dir

是的确实是这样的。但是为什么呢?
这个需要提及到环境变量的问题,我们可以看看当前文件所处的环境变量到底里面有什么?
使用下面的语句:

import sys, os
print('--------')
for path in sys.path:
    print(path)
print('--------')

其中sys.path是所有环境变量的所构成的列表,

--------
D:\0 sty file\myCode\pythonFile\Day5\bin
D:\0 sty file\myCode\pythonFile
C:\ProgramData\Anaconda3\python36.zip
C:\ProgramData\Anaconda3\DLLs
C:\ProgramData\Anaconda3\lib
C:\ProgramData\Anaconda3
C:\ProgramData\Anaconda3\lib\site-packages
C:\ProgramData\Anaconda3\lib\site-packages\Babel-2.5.0-py3.6.egg
C:\ProgramData\Anaconda3\lib\site-packages\win32
C:\ProgramData\Anaconda3\lib\site-packages\win32\lib
C:\ProgramData\Anaconda3\lib\site-packages\Pythonwin
--------

导入模块和package时候,我们的程序会从这个sys.path中从前到后寻找这些目录下有没有我们要找的模块,可以看见D:\0 sty file\myCode\pythonFile\Day5\bin是在第一个的所有我们直接导入hello模块。python找到的D:\0 sty file\myCode\pythonFile\Day5\bin里面的hello.py找到之后,就不找了,然后打印出来了。

导入的问题来了

现在问题来了,我现在就想要导入D:\0 sty file\myCode\pythonFile\Day5下面的hello,那我应该怎么办?
我们知道在python中我们可以找到当前文件所在目录的父目录,然后将他加入到运行环境时候的环境变量中去,注意是运行环境中的,因为在当前python文件运行结束后,这个环境变量就释放了。

import sys, os    # 导入系统模块
print(os.path.abspath(__file__))  #打印当前文件所处的绝对路径
print(os.path.dirname(os.path.abspath(__file__))) #打印当前文件所处的目录
# 打印当前文件所处的目录的父目录
print( os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Outputs:
# D:\0 sty file\myCode\pythonFile\Day5\bin\test.py
# D:\0 sty file\myCode\pythonFile\Day5\bin
# D:\0 sty file\myCode\pythonFile\Day5 

然后我们就可以在写下如下的代码:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)  # 将BASE_DIR加入到系统环境变量

我们将当前文件所在目录的父目录加入到环境变量中去,然后我们在打印下sys.path得到:

--------
D:\0 sty file\myCode\pythonFile\Day5\bin
D:\0 sty file\myCode\pythonFile
C:\ProgramData\Anaconda3\python36.zip
C:\ProgramData\Anaconda3\DLLs
C:\ProgramData\Anaconda3\lib
C:\ProgramData\Anaconda3
C:\ProgramData\Anaconda3\lib\site-packages
C:\ProgramData\Anaconda3\lib\site-packages\Babel-2.5.0-py3.6.egg
C:\ProgramData\Anaconda3\lib\site-packages\win32
C:\ProgramData\Anaconda3\lib\site-packages\win32\lib
C:\ProgramData\Anaconda3\lib\site-packages\Pythonwin
D:\0 sty file\myCode\pythonFile\Day5
--------

导入package

导入package时候设置环境变量的问题和导入模块是一样的,就不赘述了,但是需要注意的一点是导入package后,package下的init.py里的内容是自动执行的。
如我在test_package下的init.py中写入
print('i am in test_package __init__')
当我们在
import test_package
后就自动执行了,这在我们管理很多文件时候,进行初始化的作用相当好用啊。

但是,这种做法有如下几个缺点:

  • 如果你用PYTHONPATH,那么当有多个项目时,你需要把每个项目的根目录都加入到PYTHONPATH中,会使得PYTHONPATH变得十分臃肿
  • 如果你使用sys.path,由于文件夹是动态添加的,所以当你使用相对路径的时候,实际路径会十分依赖于你的入口函数,当入口函数改变很可能就会导致代码无法运行
  • 如果你使用绝对路径,将你的代码在其他机器上运行的时候需要重新配置这些变量,十分麻烦

创建__main__.py文件
在package的根目录中创建__main__.py文件,可以使得你的package可以通过python -m直接运行。

demo中的__main__.py文件十分简单:

CSDN:楼上小宇_home:http://blog.csdn.net/sty945

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值