首页 > 编程语言 >Python高级之模块导入

Python高级之模块导入

时间:2023-12-16 14:56:10浏览次数:22  
标签:__ Python py 导入 模块 import

模块导入与包的使用

【一】模块与包概要

模块(Module):

  1. 定义: 在Python中,模块是一个包含 Python 代码的文件。这些文件以 .py 为扩展名,可以包含变量、函数和类等,文件名为xxx.py,模块名则是xxx,导入模块可以引用模块中已经写好的功能。

  2. 作用: 模块提供了一种组织代码的方式,将相关的功能组织在一个文件中,使得代码更加清晰和可维护。

  3. 创建和使用: 创建一个模块非常简单,只需编写 Python 代码并保存为 .py 文件。其他 Python 文件可以通过 import 语句导入模块,并使用其中定义的变量、函数和类。

    # 例子:创建一个名为 mymodule.py 的模块
    # mymodule.py
    def greet(name):
        return f"Hello, {name}!"
    
    # 在其他文件中使用该模块
    # main.py
    import mymodule
    
    result = mymodule.greet("user")
    print(result)  # 输出 "Hello, user!"
    

包(Package):

  1. 定义: 包是一种将模块组织在一起的方式,它是一个包含特殊文件 __init__.py 的目录。这个目录可以包含子目录和模块文件。

  2. 作用: 包用于将相关的模块组织在一个命名空间下,避免命名冲突,并提供更好的代码结构。

  3. 创建和使用: 创建一个包也很简单,只需在目录中添加 __init__.py 文件。可以在包内创建子目录和模块,并通过 import 语句导入其中的内容。

    # 只要文件夹中有__init__.py并在__init__文件中为文件夹中的模块进行了注册就可以称为包
    mypackage/
    ├── __init__.py   # 第一层包
    ├── module1.py
    ├── module2.py
    └── subpackage/
        ├── __init__.py   # 第二层包1
        └── module3.py
    └── subpackage/
    	└── __init__.py  # 第二层包2
        └── module4.py
    

    image-20231215194858648

    # 在其他文件中使用包
    # main.py
    from mypackage import module1
    from mypackage.subpackage import module3
    
    result1 = module1.function1()
    result2 = module3.function3()
    
    print(result1)
    print(result2)
    

【二】模块的来源

  • 在 Python 中,模块的来源可以分为两类:内建模块(Built-in Modules)和外部模块(External Modules)。
  1. 内建模块(Built-in Modules): Python 提供了一些内建模块,这些模块是 Python 安装的一部分,无需额外安装。一些常用的内建模块包括 mathrandomsysos 等。这些模块提供了许多常用的功能,可以直接在 Python 程序中使用。

    import math
    
    result = math.sqrt(25)   # 取平方根
    print(result)  # 输出 5.0
    
  2. 外部模块(External Modules): 外部模块是由第三方开发者编写的,不是 Python 标准库的一部分。这些模块通常提供了各种功能和工具,可以通过 pip(Python 包管理工具)等方式进行安装。一些常用的外部模块包括 requestsnumpypandas 等。

    # 通过 pip 安装外部模块
    pip install requests
    
    import requests # 爬虫中的模块
    
    response = requests.get("https://www.example.com")
    print(response.status_code)
    
  3. 本地模块:本地模块就是你自己根据需求搭建出来的模块,可以自行编辑,创建

    # test.py
    def index(x, y):
        return x + y
    
    # main.py
    from test import index
    
    print(index(1, 2)) # 3
    

【三】导入模块(import)

  • 在 Python 中,import 语句用于导入模块,从而可以使用该模块中定义的变量、函数、类等内容。import 有多种使用方式,以下是一些常见的形式:
import foo  	# 导入模块foo
a = foo.x  		# 引用模块foo中变量x的值赋值给当前名称空间中的名字a
foo.get()  		# 调用模块foo的get函数
foo.change()    # 调用模块foo中的change函数
obj = foo.Foo() # 使用模块foo的类Foo来实例化,进一步可以执行obj.func()

1、导入整个模块:(import)

import module_name

这种形式将整个模块导入,并通过模块名前缀使用其中的内容。例如:

import math

print(math.pi)
print(math.sqrt(25))

2、给导入的模块指定别名:(import as )

import module_name as alias
# from 模块位置 import 模块名 as 自定义名字

这样可以为导入的模块指定一个别名,方便在代码中使用。例如:

import math as m

print(m.pi)

3、导入模块中的特定内容:(from import)

from module_name import name1, name2, ...

这种形式允许从模块中导入指定的变量、函数、类等,而不必使用模块名前缀。例如:

from math import pi, sqrt

print(pi)
print(sqrt(25))

4、导入模块中的所有内容(不推荐):(from mport * )

from module_name import *
  • 这种形式导入模块中的所有内容,但通常不推荐使用,因为可能引起命名冲突。最好的做法是只导入需要的内容。

  • 只能在模块最顶层使用 * 的方式导入,在函数内则非法

1.__all__

  • 模块的编写者可以在自己的文件中定义__all__变量用来控制 * 代表的意思
# foo.py

# 该列表中所有的元素必须是字符串类型,每个元素对应foo.py中的一个名字
__all__=['x','get'] 
x=1
def get():
    print(x)
def change():
    global x
    x=0
class Foo:
    def func(self):
       print('from the func')
  • 这样我们在另外一个文件中使用 * 导入时,就只能导入__all__定义的名字了
# 此时的*只代表x和get

from foo import * 

x 			#可用
get()   	#可用
change() 	#不可用
Foo() 		#不可用

【四】循环导入的问题与解决方案(circular import)

# main.py
from test import index   # 【1】从test模块名中导入index函数
def add():
    index()   # 【2】执行index函数   # 【6】再一次执行index函数,形成了循环导入circular import
 
# test.py
from main import add   # 【3】从main模块名中导入add函数
def index():   # 【4】执行index函数
    print(add())# 【5】执行add函数
  
# ImportError: cannot import name 'add' from partially initialized module 'main' (most likely due to a circular import) 

【1】解决方案介绍

循环导入是指两个或多个模块相互导入,导致无法正确加载模块的情况。这可能会导致一系列问题,例如在导入过程中产生未定义的名称错误。

  • 常用的解决思路是调整导入模块语句的位置,在你需要模块时再去延迟使用

以下是一些解决循环导入问题的常见方法:

  1. 重构代码结构: 重新组织代码,将导致循环导入的模块拆分成更小的模块或者合并它们,以减少相互依赖性。

  2. 延迟导入: 使用在需要的时候再导入的方式,可以使用 importlib 模块的 import_module 函数。这样可以避免在模块级别的导入语句中形成循环依赖。

    # 模块 A
    from importlib import import_module
    
    def func():
        B = import_module('module_B')
        B.some_function()
    
  3. 将导入语句移到模块的末尾: 将导致循环导入的导入语句移到模块末尾,这样可以推迟导入的时机,直到整个模块加载完成。

    # 在 Python 中,当一个模块被导入后,它的代码会在第一次导入时被执行,并且模块的名称空间(namespace)会被缓存起来。当再次导入同一个模块时,Python 解释器会直接使用缓存中的模块对象,而不会重新执行模块代码。
    
    # 这个特性是为了提高性能和避免重复执行模块代码。由于模块代码只在第一次导入时执行,因此在导入语句位置之后的代码执行过程中,即使存在相互导入的情况,已经导入的模块的代码也不会再次执行。
    
    # 当我们将导入语句放在模块的最后时,确保了整个模块的代码都执行完毕后才进行导入,这意味着在执行导入语句之前,相互导入的模块已经在第一次导入时完成了执行。因此,即使存在相互导入,由于 Python 解释器对模块的名称空间进行了缓存,不会重新执行模块代码,从而避免了循环导入问题。
    
    # 这种机制使得 Python 可以高效地处理相互导入的情况,前提是在导入语句的位置合理,避免循环依赖导致的无限循环。
    
  4. 使用函数或方法级别的导入: 在需要的时候通过函数或方法级别的导入来避免模块级别的导入。

    # 模块 A
    def func():
        from module_B import some_function
        some_function()
    
  5. 使用 __import__ 函数: 这是 Python 的内置函数,允许你在运行时动态导入模块,可以用于解决一些特殊的循环导入问题。

    # 模块 A
    B = __import__('module_B')
    
  6. 引入局部导入: 通过在函数或方法内进行导入,将导入限制在局部作用域,避免了全局导入造成的循环依赖。

    # 模块 A
    def func():
        import module_B
        module_B.some_function()
    

【五】搜索模块的路径与优先级

【1】模块的分类

  1. 内建模块(Built-in modules): Python 解释器首先会搜索内建模块,这些模块是 Python 安装时就包含的,无需额外安装。这些模块包括一些基础功能,如 sysmath 等。
  2. 当前目录(Current directory): 解释器会搜索当前执行脚本的目录,也就是包含当前脚本的目录。如果你的模块在当前目录中,可以直接导入。
  3. 环境变量 PYTHONPATH 中指定的目录: 你可以通过设置环境变量 PYTHONPATH 来添加自定义的模块搜索路径。这个环境变量包含一个或多个目录路径,解释器会按照这些路径搜索模块。
  4. 标准库目录(Standard library directories): Python 解释器会搜索标准库的安装目录,这是 Python 安装时默认设置的搜索路径之一。
  5. 第三方库目录(Third-party library directories): 如果你使用了第三方库,解释器会搜索这些库的安装目录。

模块搜索的优先级是按照上述顺序逐一进行的,一旦找到了匹配的模块,搜索就会停止。这也意味着如果有多个路径中包含同名的模块,解释器会使用最先找到的那个。

【2】查看模块的搜索路径

  • sys.path 也被称为模块的搜索路径,它是一个列表类型
import sys

print(sys.path)
'''
['D:\\Files\\Python\\pythonProject1', 'D:\\Files\\Python\\pythonProject1', 
'D:\\Apps\\pycharm\\PyCharm 2023.2.1\\plugins\\python\\helpers\\pycharm_display', 'D:\\Apps\\Python310\\python310.zip', 'D:\\Apps\\Python310\\DLLs', 
'D:\\Apps\\Python310\\lib', 'D:\\Apps\\Python310', 
'D:\\Apps\\Python310\\lib\\site-packages', 
'D:\\Apps\\pycharm\\PyCharm 2023.2.1\\plugins\\python\\helpers\\pycharm_matplotlib_backend']
'''
  • 列表中的每个元素其实都可以当作一个目录来看:

    • 在列表中会发现有.zip或.egg结尾的文件
      • 二者是不同形式的压缩文件
  • 事实上Python确实支持从一个压缩文件中导入模块

    • 我们也只需要把它们都当成目录去看即可。
  • sys.path 中的第一个路径通常为空,代表执行文件所在的路径,所以在被导入模块与执行文件在同一目录下时肯定是可以正常导入的

  • 而针对被导入的模块与执行文件在不同路径下的情况

    • 为了确保模块对应的源文件仍可以被找到
    • 需要将源文件 foo.py 所在的路径添加到 sys.path
    • 假设 foo.py 所在的路径为 /pythoner/projects/
    import sys
    
    # 也可以使用sys.path.insert(……)
    sys.path.append(r'/pythoner/projects/') 
    
    # 无论foo.py在何处,我们都可以导入它了
    import foo 
    
    • 作为模块foo.py的开发者
      • 可以在文件末尾基于__name__在不同应用场景下值的不同来控制文件执行不同的逻辑
    # foo.py
    ...
    if __name__ == '__main__':
    	# 被当做脚本执行时运行的代码
        foo.py
    else:
        # 被当做模块导入时运行的代码
        foo.py
    

    通常我们会在if的子代码块中编写针对模块功能的测试代码

    这样foo.py在被当做脚本运行时,就会执行测试代码

    而被当做模块导入时则不用执行测试代码。

【六】相对路径与绝对路径

【1】相对路径(Relative Path):

相对路径是相对于当前工作目录或当前脚本所在目录的路径。它描述如何从一个位置到达另一个位置。相对路径不包括根目录,直接从当前位置出发。

在相对路径中,常见的表示方法包括:

  • .:表示当前目录。
  • ..:表示父级目录。
  • 具体的目录或文件名:相对于当前位置的目录或文件名。
./subdirectory/file.txt  # 表示当前目录下的 subdirectory 文件夹中的 file.txt 文件
../parentdirectory/file.txt  # 表示父级目录下的 parentdirectory 文件夹中的 file.txt 文件

【2】绝对路径(Absolute Path)

  • 绝对路径是从文件系统的根目录开始指定文件或目录的路径。它提供了完整的路径信息,不依赖于当前工作目录。

    在绝对路径中,通常包括文件系统的根目录(如 /C:\)和一系列目录名。

# 例如,绝对路径可能是:
absolute_path = 'C:/Users/username/projects/data/file.txt'

# /home/user/documents/file.txt  # Linux 或 macOS 下的绝对路径
# C:\Users\User\Documents\file.txt  # Windows 下的绝对路径

标签:__,Python,py,导入,模块,import
From: https://www.cnblogs.com/Lea4ning/p/17904831.html

相关文章

  • Python学习之十五_不同类型数据库表内容比较
    Python学习只十五_不同类型数据库表内容比较前言最近学习力总结了很多Python相关的内容本次想继续学习一下不同数据库之间的数据比较.这样理论上可以极大的缩减不同数据库测试成本.感谢Python以及之前大拿的各种资料.这个学习还是表简单与单纯.理论上可以通过标准SQL......
  • Python学习之十六_virsh批量获取虚拟机IP地址的方法
    Python学习之十六_virsh批量获取虚拟机IP地址的方法Linux命令说明forjin\$(foriin`virshlist|grep-vId|greprunning|awk'{print$2}'`;\dovirshdumpxml$i|grep"macaddress"|awk-F\''{print$2}'&&e......
  • os模块
    os模块【一】文件操作(1)导入模块importos(2)获取当前文件路径(abspath)abspathfile_path=os.path.abspath(__file__)(3)获取当前文件所在文件夹的路径(dirname)dirnamebase_dir=os.path.dirname(__file__)(4)判断当前路径是否存在(exists)#指定一个存在的路径path_one......
  • random模块
    random模块【一】导入模块importrandom【二】随机小数(1)默认区间的小数(random)importrandom#默认是大于0且小于1之间的小数num=random.random()print(num)#0.50082157211298(2)指定区间的小数(uniform)importrandom#指定为0到5之间的随机小数res=random.u......
  • Python 以类作为装饰器 几种使用场景
    1.原函数、装饰器都没有参数代码:classTest:def__init__(self,func):print('Bein__init__process...')self.__func=funcdef__call__(self):print("...Startdecorate...")self.__func()prin......
  • 基于LSTM模型的时间序列预测(车厢重量预测),Python中Keras库实现LSTM,实现预测未来未知数
    简介LSTM是一种常用的循环神经网络,其全称为“长短期记忆网络”(LongShort-TermMemoryNetwork)。相较于传统的循环神经网络,LSTM具有更好的长期记忆能力和更强的时间序列建模能力,因此在各种自然语言处理、语音识别、时间序列预测等任务中广泛应用。问题场景:对一节火车进行装载货物,......
  • python操作文件夹
    帮我写一个python程序遍历文件夹下所有的压缩文件,如ziprar7z结尾的文件等等当然可以!以下是一个Python程序,它可以遍历指定文件夹下的所有压缩文件,如zip、rar、7z等等。你可以根据需要修改代码中的路径和文件类型。请注意,这个程序需要安装第三方库patool和pyunpack,你可以使用pip......
  • 使用Python Multiprocessing库提升代码性能
    在现代计算机编程中,利用多核处理器的能力来提高应用程序的执行速度至关重要。Python的multiprocessing库就是为此而生的,它允许程序员创建进程,这些进程可以在多个CPU核心间并行运行,从而提高程序的性能。在这篇技术博客中,我们将探索multiprocessing库的关键概念及其在Python中的应用......
  • 设计规则:模块化的力量
    这是一本比较冷门的书《设计规则:模块化的力量》,虽然豆瓣上只有58个评价,但是确实能学到很多东西。这本书对我非常深远。不是是投资,创业,还是其他领域,模块化思想都能帮上你。这本书告诉我们生万物的规则。书籍电子版PDF(建议及时保存,避免被和谐):https://pan.quark.cn/s/aa40d59295df......
  • Python NumPy 线性代数
    ​ 1、矩阵和向量积矩阵和向量积可以用 numpy.dot() 函数来计算。numpy.dot()函数的两个参数分别是矩阵和向量。1)矩阵积矩阵积是两个矩阵相乘的结果。矩阵积的计算方法是将矩阵的每一行与另一个矩阵的每一列相乘,然后将各个相乘结果相加。示例代码:PythonNumPy线性代数-......