首页 > 编程语言 >8.Python3 模块和包

8.Python3 模块和包

时间:2024-03-05 13:44:05浏览次数:18  
标签:__ Python py 导入 模块 import Python3

Python3 模块和包

为此 Python 提供了一个办法,把这些定义存放在文件中,为一些脚本或者交互式的解释器实例使用,这个文件被称为模块。模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 python 标准库的方法。代码的可重用性体现在,当编写好一个模块后,只要编程过程中需要用到该模块中的某个功能(由变量、函数、类实现),无需做重复性的编写工作,直接在程序中导入该模块即可使用该功能。

举个简单的例子,在某一目录下创建一个名为 hello.py 文件,其包含的代码如下:

def say ():
    print("Hello,World!")

在同一目录下,再创建一个 say.py 文件,其包含的代码如下:

#通过 import 关键字,将 hello.py 模块引入此文件
import hello
hello.say()

当调用模块中的 say() 函数时,使用的语法格式为“模块名.函数”,这是因为,相对于 say.py 文件,hello.py 文件中的代码自成一个命名空间,因此在调用其他模块中的函数时,需要明确指明函数的出处,否则 Python 解释器将会报错。

1.模块

1.import 语句

想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:

import 模块名1 [as 别名1], 模块名2 [as 别名2],…

使用这种语法格式的 import 语句,会导入指定模块中的所有成员(包括变量、函数、类等)。不仅如此,当需要使用模块中的成员时,需用该模块名(或别名)作为前缀,否则 Python 解释器会报错。

把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:

from modname import *

这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。

当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。搜索路径是一个解释器会先进行搜索的所有目录的列表。如想要导入模块 support,需要把命令放在脚本的顶端:

#!/usr/bin/python3
# Filename: test.py

import support # 导入support模块
import sys as s # 导入sys整个模块,并指定别名为s
 
# 现在可以调用模块里包含的函数了
support.print_func("Runoob")

以上实例输出结果:

$ python3 test.py 
Hello :  Runoob

2.from … import 语句

Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:

from 模块名 import 成员名1 [as 别名1],成员名2 [as 别名2],…

例如,要导入模块 fibo 的 fib 函数,使用如下语句:

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

这个声明不会把整个fibo模块导入到当前的命名空间中,它只会将fibo里的fib函数引入进来。

3.__name__属性

一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行。

  • __name__是一个变量,前后加了双下划线是因为这是系统定义的名字(python中系统变量都是双下划线开头结尾),普通变量不使用这种命名方式;
  • python有很多模块,这些模块是可以独立运行的(这一点与C语言和C++的头文件不同);
  • __name__是用来标识模块名字的一个系统变量。这里分两种情况:第一种情况指的是当前运行的模块,那么当前模块__name__的值就为"__main__";第二种情况指的是该模块是使用import导入的模块,那么这个被导入模块的__name__变量的值为该模块的文件名(去掉.py)。

在本模块内运行:

# test_one.py
def test_function():
  print(__name__)
 
def test1_function(name):
  print(type(name), name)

# 在本模块内运行
test_function() # 本模块内运行输出为__main__
test1_function(__name__) # 本模块内运行输出为__main__

运行输出如下:

__main__
<class 'str'> __main__

将test_one导入到test模块内运行:

# test_one.py
def test_function():
  print(__name__)
 
def test1_function(name):
  print(type(name), name)

# 在本模块内运行
test_function()
test1_function(__name__)
# test.py
from test_one import *

# 将test_one导入到test模块内运行
test_function() # 输出的test_one模块的__name__为test_one
test1_function(__name__) # 传入的本模块内的__name__为__main__

运行输出如下:

test_one
<class 'str'> __main__

4.添加模块路径的3种方式

很多初学者经常遇到这样的问题,即自定义 Python 模板后,在其它文件中用 import(或 from...import) 语句引入该文件时,Python 解释器同时如下错误:

ModuleNotFoundError: No module named '模块名'

意思是 Python 找不到这个模块名,要想解决这个问题,读者要先搞清楚 Python 解释器查找模块文件的过程。

通常情况下,当使用 import 语句导入模块后,Python 会按照以下顺序查找指定的模块文件:

  • 在当前目录,即当前执行的程序文件所在目录下查找;
  • 到 PYTHON PATH(环境变量)下的每个目录中查找;
  • 到 Python 默认的安装目录下查找。

以上所有涉及到的目录,都保存在标准模块 sys 的 sys.path 变量中,通过此变量我们可以看到指定程序文件支持查找的所有目录。换句话说,如果要导入的模块没有存储在 sys.path 显示的目录中,那么导入该模块并运行程序时,Python 解释器就会抛出 ModuleNotFoundError(未找到模块)异常。

解决“Python找不到指定模块”的方法有 3 种,分别是:

  1. 向 sys.path 中临时添加模块文件存储位置的完整路径;
  2. 将模块放在 sys.path 变量中已包含的模块加载路径中;
  3. 设置 path 系统环境变量。
import sys

sys.path
print(sys.path)

其运行结果为:

['c:\\Users\\icq\\Desktop', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\python311.zip', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\DLLs', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\Lib', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages']

导入模块方式一:临时添加模块完整路径

模块文件的存储位置,可以临时添加到 sys.path 变量中,即向 sys.path 中添加 D:\python_module,在 say.py 中的开头位置添加如下代码:

import sys
sys.path.append('D:\\python_module')

注意:在添加完整路径中,路径中的 '' 需要使用 \ 进行转义,否则会导致语法错误。

需要注意的是,通过该方法添加的目录,只能在执行当前文件的窗口中有效,窗口关闭后即失效。

导入模块方式二:将模块保存到指定位置

如果要安装某些通用性模块,比如复数功能支持的模块、矩阵计算支持的模块、图形界面支持的模块等,这些都属于对 Python 本身进行扩展的模块,这种模块应该直接安装在 Python 内部,以便被所有程序共享,此时就可借助于 Python 默认的模块加载路径。

Python 程序默认的模块加载路径保存在 sys.path 变量中,因此,我们可以在程序文件中先看看 sys.path 中保存的默认加载路径,如下所示:

['c:\\Users\\icq\\Desktop', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\python311.zip', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\DLLs', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\Lib', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311', 'C:\\Users\\icq\\AppData\\Local\\Programs\\Python\\Python311\\Lib\\site-packages']

上面的运行结果中,列出的所有路径都是 Python 默认的模块加载路径,但通常来说,我们默认将 Python 的扩展模块添加在 lib\site-packages 路径下,它专门用于存放 Python 的扩展模块和包。

所以,我们可以直接将我们已编写好的文件添加到 lib\site-packages 路径下,就相当于为 Python 扩展了一个模块,这样任何 Python 程序都可使用该模块。

导入模块方式三:设置环境变量

PYTHON PATH 环境变量(简称 path 变量)的值是很多路径组成的集合,Python 解释器会按照 path 包含的路径进行一次搜索,直到找到指定要加载的模块。当然,如果最终依旧没有找到,则 Python 就报 ModuleNotFoundError 异常。

由于不同平台,设置 path 环境变量的设置流程不尽相同,因此接下来就使用最多的 Windows、Linux、Mac OS X 这 3 个平台,可以在互联网上查询相关内容。

5.__all__变量

__all__ 变量的值是一个列表,存储的是当前模块中一些成员(变量、函数或者类)的名称。通过在模块文件中设置 __all__ 变量,当其它文件以“from 模块名 import *”的形式导入该模块时,该文件中只能使用 all 列表中指定的成员。也就是说,只有以“from 模块名 import *”形式导入的模块,当该模块设有 all 变量时,只能导入该变量指定的成员,未指定的成员是无法导入的。

def say():
    print("人生苦短,我学Python!")
def CLanguage():
    print("C语言中文网:http://c.biancheng.net")
def disPython():
    print("Python教程:http://c.biancheng.net/python")
__all__ = ["say","CLanguage"]

可见,__all__ 变量只包含 say() 和 CLanguage() 的函数名,不包含 disPython() 函数的名称。此时直接执行 文件,其执行结果为:

人生苦短,我学Python!
C语言中文网:http://c.biancheng.net
Traceback (most recent call last):
  File "C:/Users/mengma/Desktop/2.py", line 4, in <module>
    disPython()
NameError: name 'disPython' is not definedancheng.net/python")

以“import 模块名”的形式导入模块和以“from 模块名 import 成员”的形式直接导入指定成员,__all__ 变量均无作用。

2.包

包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。

现存很多种不同的音频文件格式(基本上都是通过后缀名区分的,例如: .wav,:file:.aiff,:file:.au,),所以你需要有一组不断增加的模块,用来在不同的格式之间转换。

这里给出了一种可能的包结构(在分层的文件系统中):

sound/                          顶层包
      __init__.py               初始化 sound 包
      formats/                  文件格式转换子包
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  声音效果子包
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  filters 子包
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

在导入一个包的时候,Python 会根据 sys.path 中的目录来寻找这个包中包含的子目录。目录只有包含一个叫做 init.py 的文件才会被认作是一个包。(这是 Python 2.x 的规定,而在 Python 3.x 中,init.py 对包来说,并不是必须的。)

1.包导入的三种方法

import 语句导入包

用户可以每次只导入一个包里面的特定模块,这将会导入子模块:sound.effects.echo。 他必须使用全名去访问:

import 包名[.模块名 [as 别名]] #用 [] 括起来的部分,是可选部分,即可以使用,也可以直接忽略
import sound.effects.echo
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

通过此语法格式导入包中的指定模块后,在使用该模块中的成员(变量、函数、类)时,需添加“包名.模块名”为前缀。如果使用 as 给包名.模块名”起一个别名的话,就使用直接使用这个别名作为前缀使用该模块中的方法了。

当直接导入指定包时,程序会自动执行该包所对应文件夹下的 init.py 文件中的代码,直接导入包名,并不会将包中所有模块全部导入到程序中,它的作用仅仅是导入并执行包下的 init.py 文件,包的本质就是模块,导入模块时,当前程序中会包含一个和模块名同名且类型为 module 的变量,导入包也是如此

from … import 语句导入包

这同样会导入子模块: echo,并且他不需要那些冗长的前缀,所以他可以这样使用:

from 包名 import 模块名 [as 别名] #用 [] 括起来的部分,是可选部分,即可以使用,也可以直接忽略
from sound.effects import echo
echo.echofilter(input, output, delay=0.7, atten=4)

使用此语法格式导入包中模块后,在使用其成员时不需要带包名前缀,但需要带模块名前缀。既然包也是模块,那么这种语法格式自然也支持 from 包名 import * 这种写法,它和 import 包名 的作用一样,都只是将该包的 init.py 文件导入并执行。

from … import 语句导入函数或者变量

同样的,这种方法会导入子模块: echo,并且可以直接使用他的 echofilter() 函数:

from 包名.模块名 import 成员名 [as 别名] #用 [] 括起来的部分,是可选部分,即可以使用,也可以直接忽略
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)

通过该方式导入的变量(函数、类),在使用时可以直接使用变量名(函数名、类名)调用,在使用此种语法格式加载指定包的指定模块时,可以使用 * 代替成员名,表示加载该模块下的所有成员

2.包的__all__变量

如果我们使用 from sound.effects import * ,Python 会进入文件系统,找到这个包里面所有的子模块,然后一个一个的把它们都导入进来。但这个方法在 Windows 平台上工作的就不是非常好,因为 Windows 是一个不区分大小写的系统。为了解决这个问题,我们只需要提供一个精确包的索引。

如果包定义文件 init.py 存在一个叫做 all 的列表变量,那么在使用 from package import * 的时候就把这个列表中的所有名字作为包内容导入。

以下实例在 file:sounds/effects/init.py 中包含如下代码:

__all__ = ["echo", "surround", "reverse"]

这表示当你使用from sound.effects import *这种用法时,你只会导入包里面这三个子模块。

如果 all 真的没有定义,那么使用from sound.effects import *这种语法的时候,就不会导入包 sound.effects 里的任何子模块。他只是把包sound.effects和它里面定义的所有内容导入进来(可能运行__init__.py里定义的初始化代码)。使用 from Package import specific_submodule 这种方法永远不会有错。事实上,这也是推荐的方法。除非是你要导入的子模块有可能和其他包的子模块重名。

3.dir() 函数

dir() 函数用来列出某个类或者某个模块中的全部内容,包括变量、方法、函数和类等,它的用法为:

dir(obj)

obj 表示要查看的对象。obj 可以不写,此时 dir() 会列出当前范围内的变量、方法和定义的类型。

这里以导入 string 模块为例,下面通过 dir() 函数查看该模块中包含哪些成员:

import string
print(dir(string))

程序执行结果为:

['Formatter', 'Template', '_ChainMap', '_TemplateMetaclass', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_re', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']

通过 dir() 函数获取到的模块成员,不仅包含供外部文件使用的成员,还包含很多“特殊”(名称以 2 个下划线开头和结束)的成员,列出这些成员,对我们并没有实际意义。

因此,这里给读者推荐一种可以忽略显示 dir() 函数输出的特殊成员的方法。以 string 模块为例:

import string
print([e for e in dir(string) if not e.startswith('_')])

程序执行结果为:

['Formatter', 'Template', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']

显然通过列表推导式,可在 dir() 函数输出结果的基础上,筛选出对我们有用的成员并显示出来。

除了使用 dir() 函数之外,还可以使用 all 变量,借助该变量也可以查看模块(包)内包含的所有成员。

仍以 string 模块为例,举个例子:

import stringprint(string.__all__)

程序执行结果为:

['ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace', 'Formatter', 'Template']

和 dir() 函数相比,all 变量在查看指定模块成员时,它不会显示模块中的特殊成员,同时还会根据成员的名称进行排序显示。不过需要注意的是,并非所有的模块都支持使用 all 变量,因此对于获取有些模块的成员,就只能使用 dir() 函数。

4.help()函数

在使用 dir() 函数和 all 变量的基础上,虽然我们能知晓指定模块(或包)中所有可用的成员(变量、函数和类),但对于以上的输出结果,对于不熟悉 string 模块的用户,还是不清楚这些名称分别表示的是什么意思,更不清楚各个成员有什么功能。针对这种情况,我们可以使用 help() 函数来获取指定成员(甚至是该模块)的帮助信息。

Python help() 函数用来查看某个函数或者模块的帮助文档,它的用法为:

help(obj)

obj 表示要查看的对象。obj 可以不写,此时 help() 会进入帮助子程序。

掌握了以上两个函数,我们就可以自行查阅 Python 中所有方法、函数、变量、类的用法和功能了。

之所以我们可以使用 help() 函数查看具体成员的信息,是因为该成员本身就包含表示自身身份的说明文档(本质是字符串,位于该成员内部开头的位置)。无论是函数还是类,都可以使用 doc 属性获取它们的说明文档,模块也不例外(help() 函数底层也是借助 doc 属性实现的)。

5. __file__属性

当指定模块(或包)没有说明文档时,仅通过 help() 函数或者 doc 属性,无法有效帮助我们理解该模块(包)的具体功能。在这种情况下,我们可以通过 file 属性查找该模块(或包)文件所在的具体存储位置,直接查看其源代码。

以 string 模块为例:

import string
print(string.__file__)

程序输出结果为:

D:\python3.6\lib\string.py

由此,通过调用 file 属性输出的绝对路径,我们可以很轻易地找到该模块(或包)的源文件。

并不是所有模块都提供 file 属性,因为并不是所有模块的实现都采用Python语言,有些模块采用的是其它编程语言(如 C 语言)。

标签:__,Python,py,导入,模块,import,Python3
From: https://www.cnblogs.com/littlecamel/p/18053864

相关文章

  • 深入解析ASP.NET Core MVC应用的模块化设计[上篇]
    ASP.NETCoreMVC的“模块化”设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载。这种为“飞行中的飞机加油”的方案是如何实现的呢?该系列的两篇文章将关注于这个主题,本篇着重介绍“模块化”的总体设计,下篇我们将演示将介绍“分散定......
  • ems-jsp 用户登录模块
    整体思路1.登录首先要从前端获取账号和密码2.根据用户名去查询用户,用户存在比对密码(注意由于密码是加密存入数据库的所以比对时要用用户输入的密码加密后跟数据库中的密码比对)。  用户不存在,登陆失败,返回登录界面并且显示失败原因。代码:展示部分Controller层:@Requ......
  • python3.6.8 安装解决ssl问题
    https://www.cnblogs.com/mqxs/p/9103031.html#!/bin/bashecho"正在安装相关组件"yuminstall-yopenssl-develbzip2-develexpat-develgdbm-develreadline-develsqlite-develgcc-c++gccopenssl-develecho"下载安装包"wgethttps://www.python.org/ft......
  • WIFI&蓝牙(ESP32)转CAN总线&串口TTL模块-B1-设备作为TCP客户端连接TCP服务器,实现RS48
    <p><iframename="ifd"src="https://mnifdv.cn/resource/cnblogs/ESP32_CAN"frameborder="0"scrolling="auto"width="100%"height="1500"></iframe></p>说明这节测试的是让设备连接路由器,然后设备以......
  • BOSHIDA DC电源模块的工作原理及应用
    BOSHIDADC电源模块的工作原理及应用DC电源模块是一种常见的电子元件,它具有将交流电转换为直流电的功能。在很多电子设备中,尤其是需要稳定的直流电源供应的设备中,DC电源模块被广泛应用。 DC电源模块的工作原理可以简单描述如下:将输入的交流电转换为直流电。首先,交流电输入到......
  • time模块实现进度条
    显示进度条defmyprocess(percent):ifpercent>1:percent=1#打印对应的#号数量*"#"=>字符串#号效果strvar=int(percent*50)*"#"#进行打印%%=>%print("\r[%-50s]%d%%"%(strvar,percent*100),end="")接受数据rec......
  • dnn模块
    代码案例#导入工具包importutils_pathsimportnumpyasnpimportcv2#标签文件处理rows=open("synset_words.txt").read().strip().split("\n")classes=[r[r.find("")+1:].split(",")[0]forrinrows]#Caffe所需配置文件net=c......
  • Zip模块
    ZIP模块压缩模块的动作应该是打包->压缩构造def__init__(self,file,mode="r",compression=ZIP_STORED,allowZip64=True,compresslevel=None,*,strict_timestamps=True):#功能:创建一个ZipFile对象,表示一个zip文件.#参数:"""-参数file......
  • python hashlib模块详解
    hashlib是python自带的加密模块,提供了一些基础常用的加密方式,如:md5(),sha1(),sha224(),sha256(),sha384(),sha512(),blake2b(),blake2s() Hash对象提供了4个方法: --update(data):更新hash对象的字节数据,data是需要加密的文本内容,需要转为bytes类型,如果”abc123”.en......
  • time模块
    Time模块importtime时间戳指从1970年1月1日0时0分0秒到指定时间之间的秒数,时间戳是秒,可以使用到2038年的某一天UTC时间世界约定的时间表示方式,世界统一时间格式,世界协调时间!夏令时在夏令时时间状态下,时间会调块1个小时时间元组是使用元祖格式表示时间的一种方式格式......