Python 模块与包-下划线

1、模块与包

1.1 定义

模块(库)

 就是Python文件,里面定义了很多的函数、类、变量。
一个完整大型的python程序是由模块和包的形式组织起来的,可见模块在python中的重要性

python包

实际上就是一个目录,目录里面可以有一个 _init_.py

1.2 分类

  • 标准模块(无需安装,python自带)—— import random
  • 第三模块(需要安装)——pip install requests、import requests
  • 自定义模块(自己写的)

一个模块的运行有俩种方式

  • 直接运行(python 文件)、
  • 导入运行(import 文件)
sys模块是专门对python进行处理的模块,模块就是.py文件,里面有很多函数。
os模块是专门对操作系统进行处理的模块

1.3 python2 VS python3

  • init.py 在p2里面是必须要的,包必须是package
    但是在p3中是可选的,包可以是directory
    init.py是包的初始化文件
  • pyc文件 模块导入运行的时候 p2会再同级目录下会创建一个pyc文件
    p3则会创建一个__pycache__文件夹,里面放了pyc文件
对于主程序而言pyc是临时性的,主程序结束后,从内存里面消失,不会落地到磁盘。

对于导入的文件pyc文件保存到磁盘,节省了重复性翻译。

导入的文件,相当于重复性代码,翻译成字节码,存到__pycache__里面落地到磁盘。

主程序翻译成字节码,__pycache__不落地到磁盘。少了一步从源代码到pyc的翻译过程。

1.4 模块导入

第一次导入,就会将这个模块加载到内存空间
下一次导入的时候,会查看内存空间有没有,有的话就直接拷贝

a) 静态导入

import string  #方式1:直接导入模块
print(string.digits)   

from string import * #方式2:导入所有函数(不推荐使用*这样导入)
print(digits)

from string import digits #方式3 从模块里面导入函数/从包是导入模块
print(digits)

b) 动态导入

import importlib

while True:
    str1 = input("请输入你要导入的模块:")
    if str1 == 'q':
        break
    else:
        module = importlib.import_module(str1)
        print(f"{module}导入成功")
        print("查看属性:", dir(module))

c) 绝对导入

相对于top_level所在路径的绝对位置
重要的是关注程序入口在哪里 top_level

d) 相对导入

推荐使用相对导入,直接运行的文件在哪里,那一层的目录就叫top-level,之下的模块不可访问top-level同级的文件。
模块路径由. 开始的 ,不能识别到top_level 那一层,只能识别到top_level以下层
在这里插入图片描述

print("I am subpk01")  # subpk01.py

from ..subpack02 import subpk02
from pack01.subpack02 import subpk02
直接运行这个程序是不成功的,因为执行时当前层就是top—level,
相对或绝对路径都访问到了top—level的以上层
在mod.py 导入这个模块可以执行成功,以为此时top—level是pack01所在层

1.3 模块的查找

- sys.modules 查看当前空间导入的模块
  Python 中所有加载到内存的模块都放在sys.modules
- 导入模块时在sys.modules列表里查找是否已经加载了该模块,
  加载了的话导入的时候只是将模块名加载到Local名字空间中。
  没加载就会从sys.path目录中从指定路径左到右查找模块文件
  如果都没有找到模块名就报错

sys.modules是一个字典,sys.path是一个列表

# 第一个引号是当前目录下,最后一个引号内容是第三方库下载路径,pip install下载的模块会放在这个路径下
# Python查找包的顺序在sys.path中逐次查询,即从当前目录开始,至第三方库下载目录为止
>>> import sys
>>> sys.path     #注:第一个为空,表示当前路径
['', '/usr/lib64/python36.zip', '/usr/lib64/python3.6', '/usr/lib64/python3.6/lib-dynload', '/usr/local/lib/python3.6/site-packages', '/usr/lib64/python3.6/site-packages', '/usr/lib/python3.6/site-packages']
>>> sys.modules
{'builtins': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_thread': <module '_thread' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'posix': <module 'posix' (built-in)>,。。。}

1.4 重复导入问题

同一个模块重复导入
·当同一个模块重复导入时,只执行第一次
因为第1次导入,就会加载在内存中,下一次导入的时候,会先查看内存中有没有

from pack01 import one
from pack01 import one      # 注:导入2次,只执行第1次

导入重名的模块
·两个都会执行,当前生效的是后导入的模块

main.py	
from pack01.one import packtest
from pack02.three import packtest
packtest()

导入相同的模块名,使用后导入的
解决方法:取别名 [重名的模块,as取别名]

from pack01.one import packtest as packtest_01
from pack02.three import packtest
packtest_01()
packtest()
import pandas as pd
pd.to_date()

2、下划线

下划线的特殊含义(模块)

  • 以单下划线开头的(_foo)
    表示保护对象,不能用 from xxx import * 导入包/模块
  • 以双下划线开头的(__foo)
    表示私有对象,不能用 from xxx import * 导入包/模块
  • 以双下划线开头和结尾的(_foo_)
    代表Python中特殊方法专用的标识,不建议用户使用这种命名方式。

2.1 __ name __

当模块直接运行的时候,值为__main__
当模块导入运行的时候,值为模块的绝对路径

以下划线开头的变量或函数或类,是无法被模糊导入的
以双下划线开头或结尾的,都是python的特殊标识

# from pack02.One import *  模糊导入
from pack02 import One   精确导入
print(One._a)
print(One.__a)

2.2 __ all __

来模糊导入的

from pack02 import *  #这个* 是由pack02平级的__init__.py 决定的
print("I am __init__.py")   #__init__.py

# 用来模糊导入的
__all__ = ["One", "Two", "Three"]  
# 定义了*  在模糊导入的时候所指定要导入导入的模块

2.3 __ import __

__import__() 函数用于动态加载类和函数 。
如果一个模块经常变化就可以使用 import() 来动态载入。
返回元组列表

# a.py
import os   
print ('在 a.py 文件中 %s' % id(os))

# test.py
import sys  
__import__('a')  
# 导入 a.py 模块,执行结果:在 a.py 文件中 4394716136

2.4 __ file __

打印当前模块在系统中的绝对路径

import os, sys

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
print("BASE_DIR的路径为:", BASE_DIR)

print(os.path.abspath(__file__))
print(os.path.dirname(os.path.abspath(__file__)))
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

print("########################")
print(os.path.abspath(".."))
print(os.path.dirname(os.path.abspath("..")))
print(os.path.dirname(os.path.dirname(os.path.abspath(".."))))

结果:

D:\Python3.9\python.exe "E:/python项目/CJH/learn_code/11-22 模块与包/mod.py"
BASE_DIR的路径为: E:\python项目\CJH\learn_code
E:\python项目\CJH\learn_code\11-22 模块与包\mod.py
E:\python项目\CJH\learn_code\11-22 模块与包
E:\python项目\CJH\learn_code
########################
E:\python项目\CJH\learn_code
E:\python项目\CJH
E:\python项目

3、 文件与模块的执行过程

3.1 Python文件执行的过程

1、语法分析
2、编译成字节码.pyc
3、对字节码编译成二进制在这里插入图片描述

字节码文件 直接运行不会保存下来, 导入运行会保存在磁盘上,以.pyc结尾,下次再进行导入运行的时候就直接查看字节码文件即可,不需要重新编译成字节码

对于主程序而言pyc是临时性的,主程序结束以后,从内存里消失,pyc文件不会被落地到磁盘
对于导入的文件 pyc文件保存到磁盘,节省了重复性翻译
导入的文件,相当于重复性的代码段,翻译成字节码,存到__pycache__里面,落地到磁盘。
少了一步从源代码到Pyc的翻译过程

3.2 Python模块导入执行的过程

·通过sys.path环境变量找到模块文件
·编译成字节码文件(pyc文件)
·如果字节码过期了会自动重新生成
·如果字节码文件已存在则直接导入字节码文件
·执行模块中的代码来创建所定义的对象

4、模块的打包与发布

打包步骤:
1、创建模块包 sanle 需要一个__init__.py
2、在sanle 同级目录下创建一个 打包配置文件setup.py

from setuptools import setup, find_packages

setup(
    #包名
    name = "sc",
    #官网
    url = "http://www.sanchuangedu.cn",
    #版本号
    version = "0.0.1",
    #指定要打包的模块和包
    packages = find_packages(),
    #作者
    author = "wen",
    #邮箱
    author_email = "343292019@qq.com",
    #依赖
    install_requires = ['xlrd>=1.1.0'],
    #描述信息
    description = "this is test package"
)

3、python3 setup.py check 运行检查脚本
4、python3 setup.py sdist 打包
生成dist文件夹,里面包含了sc-0.0.1.tar.gz

drwxr-xr-x 2 root root  29 1123 15:05 dist
drwxr-xr-x 2 root root  45 1123 14:42 sanle
drwxr-xr-x 2 root root 110 1123 15:05 sc.egg-info
-rw-r--r-- 1 root root 418 1123 14:57 setup.py

5、进入dist 目录,pip3 install sc-0.0.1.tar.gz安装
6、进入python3 交互式环境 进行测试

[root@kafka01 ~]# python3
Python 3.6.8 (default, Aug 24 2020, 17:57:11)
[GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from sanle import sanchuang
this is sanchuang
>>> sanchuang.func1()
this is func1
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

这个手刹不太灵儿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值