我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python实现创建模块的方法详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python实现创建模块的方法详解

楔子

导入一个模块,我们一般都会使用 import 关键字,但有些场景下 import 难以满足我们的需要。所以除了 import 之外还有很多其它导入模块的方式,下面就来介绍一下。

__import__

这是一个内置函数,解释器在 import 的时候,实际上就执行了这个函数。

# import os 等价于如下方式
os = __import__("os")
print(os)  # <module 'os' from 'C:\\python38\\lib\\os.py'>

# 但是这种方式不能多级导入
path = __import__("os.path")
print(path)  # <module 'os' from 'C:\\python38\\lib\\os.py'>
# 可以看到,导入的仍是 os,而不是 os.path

# 如果想导入子模块,需要一个参数 fromlist
# 我们给它传一个非空列表即可
path = __import__("os.path", fromlist=[""])
print(path)  # <module 'ntpath' from 'C:\\python38\\lib\\ntpath.py'>

但是官方不建议使用这个函数,因为它是专门给解释器用的,我们可以使用一个模块。

import importlib

os = importlib.import_module("os")
print(os)  # <module 'os' from 'C:\\python38\\lib\\os.py'>

# 可以多级导入
path = importlib.import_module("os.path")
print(path)  # <module 'ntpath' from 'C:\\python38\\lib\\ntpath.py'>

所以当导入的模块名以字符串的形式存在时,或者模块名不符合规范时,就可以使用这种方式。

importlib.machinery

importlib.machinery 里面提供了三种 Loader,可以让我们以打开文件的方式导入一个模块。

from importlib.machinery import (
    SourceFileLoader,  # 导入源文件
    SourcelessFileLoader,  # 导入 pyc 文件
    ExtensionFileLoader  # 导入扩展文件
)

# 参数一:给模块起个名字
# 参数二:文件路径
os = SourceFileLoader(
    "我是 os 模块",
    r"C:\python38\lib\os.py"
).load_module()
print(os)
"""
<module '我是 os 模块' from 'C:\\python38\\lib\\os.py'>
"""
print(os.path.join("video", "overwatch", "hanzo.mp4"))
"""
video\overwatch\hanzo.mp4
"""

# 我们看到结果一切正常,但有一点需要注意
# 如果是导入包的话,那么要导入包里面的 __init__.py 文件
pd = SourceFileLoader(
    "我是 pandas 模块",
    r"C:\python38\lib\site-packages\pandas\__init__.py"
).load_module()
print(pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]}))
"""
   a  b
0  1  4
1  2  5
2  3  6
"""

# 如果只写到 pandas,那么会抛出 PermissionError
# 因为我们不能把目录当成文件来读取
# 至于 import 一个包,本质上也是加载包内部的 __init__.py 
# 但这里需要我们显式地加上 __init__.py

同理加载 pyc 和 pyd 也是类似的,但需要注意的是,加载普通文件和 pyc 文件时,我们可以随便起名字,也就是第一个参数任意。但对于 pyd 文件,第一个参数必须和 pyd 文件的名字保持一致。

通过 module 类创建模块

Python 一切皆对象,模块自然也不例外。既然是对象,那么必然就会有相应的类来实例化它。

import os
import hashlib
import numpy

# os.__class__ 等价于 type(os)
print(os.__class__)  # <class 'module'>
print(hashlib.__class__)  # <class 'module'>
print(numpy.__class__)  # <class 'module'>

在 Python 里面,我们一般会把单独的可导入文件称之为模块,把包含多个模块的目录称之为。通过模块和包,我们可以对项目进行功能上的划分,分门别类地进行组织。

但不管是模块、还是包,它们都是 module 这个类的实例对象,打印结果也能说明这一点。所以从解释器的角度来看的话,模块和包区分的并没有那么明显,直接把包看做是包内部的 __init__.py 即可。

既然模块的类型是 class module,那么我们是不是也可以通过调用类型对象的方式创建呢?显然是可以的,但是 module 这个类解释器没有暴露给我们,直接用的话会提示变量 module 未定义。所以只能先随便导入一个模块,然后通过 type 函数或者 __class__ 属性获取。

# 不过 types 模块内部已经帮我们做好了
# ModuleType = type(sys)
from types import ModuleType

print(ModuleType)  # <class 'module'>

# 类对象有了,下面就可以创建了
# module 类接收两个参数
# 参数一:模块的名字,必须传递
# 参数二:模块的 doc,不传默认为 None
satori = ModuleType("古明地觉", "模块的名字是一个女孩,她来自地灵殿")
print(satori)  # <module '古明地觉'>
print(satori.__doc__)  # 模块的名字是一个女孩,她来自地灵殿


# 但此时模块里面是没啥东西的,我们加一些属性吧
# 操作模块本质上是在操作它的属性字典
code = """
age = 16

def foo():
    return "^_^"
"""
# 执行 code,结果会体现在 satori 的属性字典中
exec(code, satori.__dict__)
print(satori.age)  # 16
print(satori.foo())  # ^_^

需要注意的是里面 exec 函数,它会把字符串当成代码来执行,所以这就要求字符串的来源必须是可靠的,我们能够确保不会出现恶意内容。而如果是用户传递的字符串,那么绝不能用 exec 来执行,当然 eval 也是同理。

然后是 exec 的第二个参数,表示执行时的名字空间,默认是全局名字空间。所以当不指定第二个参数时,exec(code) 相当于创建了两个全局变量:age 和 foo。

code = """
age = 16

def foo():
    return "^_^"
"""

exec(code)
print(age)  # 16
print(foo())  # ^_^

但是我们在执行的时候,将它换成了 satori.__dict__,所以结果相当于给模块添加了两个变量,或者说属性。

将一个类的实例变成一个模块

如果想将一个类的实例变成模块,那么这个类应该继承 ModuleType。

import sys
from types import ModuleType


class A(ModuleType):

    def __init__(self, module_name):
        super().__init__(module_name)

    def __getattr__(self, item):
        return f"不存在的属性: {item}"

    def __setattr__(self, key, value):
        self.__dict__[key] = value

    def __str__(self):
        return f"<module '{self.__name__}' from '我来自于虚无'>"


a = A("我是 A")
print(a)  # <module '我是 A' from '我来自于虚无'>
print(a.__name__)  # 我是 A
print(a.xx)  # 不存在的属性: xx
a.xx = "xx"
print(a.xx)  # xx

# 加入到 sys.modules 中
sys.modules["嘿嘿"] = a
import 嘿嘿
print(嘿嘿.xx)  # xx
print(嘿嘿.yy)  # 不存在的属性: yy

是不是很好玩呢?

小结

以上就是加载模块的几种方式,主要用途如下:

  • 导入一个在 sys.path 中的模块,并且模块名已知,那么直接使用 import 关键字即可;
  • 导入一个在 sys.path 中的模块,但模块名是运行时的一个字符串,那么使用 importlib 模块的 import_module 函数;
  • 导入一个不在 sys.path 中的模块,使用 importlib.machinery 的各种 Loader,只要把模块的路径传进去即可。当然啦,位于 sys.path 中的模块也可以使用该方法,但显然此时使用前两种更为方便;
  • 直接创建一个模块,通过继承 module 类来实现,并且还可以加入到 sys.modules 中。Python 有一个第三方模块叫 sh,顾名思义是用来执行 Linux Shell 命令的,它内部就使用了继承 module 类来创建模块的这种方式。但是要知道 module 这个类解释器没有暴露给我们,我们需要通过 type(模块) 或者 模块.__class__ 的方式获取;

到此这篇关于Python实现创建模块的方法详解的文章就介绍到这了,更多相关Python创建模块内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python实现创建模块的方法详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

python下thread模块创建线程的方法

本篇内容介绍了“python下thread模块创建线程的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!thread方法对创建线程有效且直
2023-06-20

Python利用Beautiful Soup模块创建对象详解

安装 通过 pip 安装 Beautiful Soup 模块:pip install beautifulsoup4 。 还可以使用 PyCharm IDE 来写代码,在 PyCharm 中的 Preferences 中找到 Project
2022-06-04

Python构建区块链的方法详解

区块链(Blockchain)是一种分布式账本(listributedledger),它是一种仅供增加(append-only),内容不可变(immutable)的有序(ordered)链式数据结构,该数据结构由网络中的一系列节点共同维护,并且这些节点之间互不信任
2023-02-25

打包发布Python模块的方法详解

前言 昨天把自己的VASP文件处理库进行了打包并上传到PyPI,现在可以直接通过pip和easy_install来安装VASPy啦(同时欢迎使用VASP做计算化学的童鞋们加星和参与进来), VASPy的GotHub地址:https://gi
2022-06-04

详解Python使用simplejson模块解析JSON的方法

1,Json模块介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScript Programming Language, Stan
2022-06-04

JavaScript实现组件化和模块化方法详解

这篇文章主要介绍了JavaScript实现组件化和模块化方法,模块化主要是指一个JS文件就是一个模块,向外提供特定功能的程序,组件化的中心思想其实跟模块化是大同小异的,感兴趣想要详细了解可以参考下文
2023-05-20

Python利用arcpy模块实现栅格的创建与拼接

这篇文章主要为大家详细介绍了如何基于Python语言arcpy模块,实现栅格影像图层建立与多幅遥感影像数据批量拼接(Mosaic)的操作,感兴趣的可以了解一下
2023-02-24

详解Python中heapq模块的用法

heapq 模块提供了堆算法。heapq是一种子节点和父节点排序的树形数据结构。这个模块提供heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2]。为了比较不存在的元素被人为是无限大的。heap最
2022-06-04

Python hashlib模块详细讲解使用方法

hashlib 是一个提供了一些流行的hash算法的 Python 标准库.其中所包括的算法有 md5, sha1, sha224, sha256, sha384, sha512. 另外,模块中所定义的 new(name, string=”) 方法可通过指定系统所支持的hash算法来构造相应的hash对象
2022-11-13

一文详解Python中itertools模块的使用方法

itertools是python内置的模块,使用简单且功能强大。这篇文章主要为大家详细介绍了itertools模块的使用方法,感兴趣的小伙伴可以了解一下
2023-03-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录