将 py 文件编译成 pyd 文件

文章目录

  • 一、简介
    • 1.1、Python中的文件类型:.py + .pyc + .pyd
    • 1.2、基本原理
      • 1.2.1、函数详解:Extension() —— 用于定义扩展模块(C/C++ 扩展)的类
      • 1.2.2、函数详解:setup() —— 用于配置和构建包的函数
  • 二、构建过程
    • 2.0、环境配置
    • 2.1、第一步:构建 setup.py 脚本(需手动指定)
      • 2.1.1、构建 setup.py 脚本(方式一):基于 setup() 函数
      • 2.1.2、构建 setup.py 脚本(方式二):基于 Extension() + setup() 函数
    • 2.2、第二步:将 .py 文件编译成 .pyd 文件:python setup.py build_ext --inplace
    • 2.3、pyd 模块的导入与使用
  • 四、(批量)将 .py 文件编译成 .pyd 文件(自动执行)

一、简介

1.1、Python中的文件类型:.py + .pyc + .pyd

py是明文且易读,pyc不易读但易被反编译,pyd不易读且不易被反编译(用于代码加密)。

  • 源代码文件 (.py):Python 的源代码文件以 .py 为扩展名,其中包含了 Python 代码的文本内容。这些文件可以直接编辑,并且可以通过 Python 解释器执行。
  • 字节码文件 (.pyc)当 Python 的源代码文件被导入时,Python 解释器会将其编译成字节码,并将字节码保存在以 .pyc 为扩展名的文件中。这些文件是 Python 解释器优化后的版本,用于加快导入模块的速度。如果 Python 源代码文件发生了改变,Python 解释器会自动重新生成对应的 .pyc 文件。
    • 使用 py_compile 将 .py 文件编译成 .pyc 文件python -m py_compile xxx.py
      • 特点:难以阅读,但很容易被反编译工具反编译回可读的源代码(如: uncompyle6)。
  • 动态链接库 (.pyd):在 Windows 平台上,Python 的扩展模块通常以 .pyd 为扩展名,它们是用 C 或 C++ 编写的,并且提供了对其他语言编写的库和系统调用的接口。.pyd 文件通常包含了用 C 或 C++ 编写的扩展模块,它们可以通过 Python 解释器导入,并且提供了对其它语言编写的库和系统调用的接口。
    • 使用 Cython 将 .py 文件编译成 C 扩展模块,从而生成二进制 .pyc 文件python setup.py build_ext
      • 特点:提高了反编译的难度。但反汇编工具仍可以对二进制文件进行逆向工程,尽管难度更大。编译过程复杂,可能需要配置额外的工具链。

1.2、基本原理

  • 使用函数 Extension() + setup() 构建 setup.py 扩展模块
  • 使用命令 python setup.py build_ext --inplace 生成扩展模块文件
    • Windows平台下,生成 .pyd 文件
    • Unix/Linux平台下,生成 .so 文件

1.2.1、函数详解:Extension() —— 用于定义扩展模块(C/C++ 扩展)的类

"""#########################################################################
# 函数功能:Python 中用于定义扩展模块(C/C++ 扩展)的类。
#         ———— 通过 Extension 类,可以指定扩展模块的名称、源文件的路径、编译选项等信息,从而在构建扩展模块时提供必要的配置。
# 函数说明:Extension(name, sources, include_dirs=None, define_macros=None, undef_macros=None,
#                   library_dirs=None, libraries=None, runtime_library_dirs=None,
#                   extra_objects=None, extra_compile_args=None, extra_link_args=None, export_symbols=None,
#                   swig_opts=None, depends=None, language=None)
# 参数说明:
#       - name:           扩展模块的名称,即在 Python 中导入时使用的名称。
#       - sources:        源文件的路径列表,可以是 .c、.cpp、.pyx 等类型的文件。
#         include_dirs:   包含的头文件目录列表。
#         define_macros:  宏定义列表,例如 [(<macro_name>, <macro_value>)]。
#         undef_macros:   要取消定义的宏列表。
#         library_dirs:   库文件目录列表。
#         libraries:      要链接的库文件列表。
#         runtime_library_dirs:运行时库文件目录列表。
#         extra_objects:  额外的目标文件列表。
#         extra_compile_args:额外的编译选项列表。
#         extra_link_args:额外的链接选项列表。
#         export_symbols: 导出的符号列表。
#         swig_opts:      用于 SWIG 扩展的额外选项。
#         depends:        依赖的文件列表。
#         language:       源文件的编程语言,例如 'c' 或 'c++'。
#########################################################################"""

1.2.2、函数详解:setup() —— 用于配置和构建包的函数

"""#########################################################################
# 函数功能:Python 中用于配置和构建包的函数,通常在 setup.py 脚本中使用。
#         ———— 通过 setup 函数,可以指定包的名称、版本、作者信息、依赖关系、入口点等信息,并配置构建和安装过程。
# 函数说明:setup(**attrs)
# 参数说明:
#         attrs:一个字典,包含了配置信息和选项。常用的参数包括:
#           - name:包的名称。
#             version:包的版本号。
#             author:包的作者名称。
#             author_email:作者的电子邮箱地址。
#             description:包的简要描述。
#             long_description:包的详细描述。
#             packages:包含的子包列表。
#             install_requires:依赖的其他包列表。
#             entry_points:包的入口点。
#           - ext_modules:扩展模块列表。
#             package_data:包含的数据文件列表。
#             scripts:可执行脚本文件列表。
#             classifiers:包的分类列表。
#             license:包的许可证。
#########################################################################"""

二、构建过程

在这里插入图片描述

2.0、环境配置

pip install python
pip install cython

2.1、第一步:构建 setup.py 脚本(需手动指定)

  • 报错提示error: unknown file type '.py' (from 'F:\py\sample.py')
  • 原因分析:试图将 Python 源文件直接传递给 Extension 对象,而它期望的是 C/C++ 源文件。
  • 解决方案:使用 Cython 的 cythonize() 函数,将 Python 文件转换为 C/C++ 扩展模块,然后再将其传递给 Extension 对象。

2.1.1、构建 setup.py 脚本(方式一):基于 setup() 函数

from setuptools import setup
from Cython.Build import cythonizesetup(name='my_module', ext_modules=cythonize(r'F:\py\temp\my_module.py'))

2.1.2、构建 setup.py 脚本(方式二):基于 Extension() + setup() 函数

from setuptools import setup, Extension
from Cython.Build import cythonize# 定义(单个)扩展模块
ext_modules = Extension(name="my_module", sources=[r"F:\py\temp\my_module.py"])"""
# 定义(多个)扩展模块
ext_modules = [Extension(name="my_module1", sources=[r"F:\py\temp\my_module1.py"]),Extension(name="my_module2", sources=[r"F:\py\temp\my_module2.py"]),# 添加更多的扩展模块...
]
"""# 使用 cythonize() 函数将扩展模块编译为 C/C++ 扩展模块,并将其传递给 ext_modules 参数。
setup(ext_modules=cythonize(ext_modules))

2.2、第二步:将 .py 文件编译成 .pyd 文件:python setup.py build_ext --inplace

在命令行中,执行命令:python setup.py build_ext --inplace

  • python: Python 解释器可执行文件的路径(默认使用环境变量的配置路径)。
  • setup.py:Python 脚本文件,用于定义 Python 包的构建和安装方式。通常,这个文件会包含一些元数据和构建指令,以告诉 setuptools(Python 的一个包管理工具)如何构建和安装这个包。
  • python setup.py:使用 python 命令,执行 Python 脚本文件。
  • build_ext: Python 定义的一个命令,用于构建扩展模块。
  • --inplace:可选。表示编译后的 .pyd 文件保存在默认的构建目录中,复制一份到当前目录中。
    • 默认路径:build\lib.win-amd64-cpython-39\my_module.cp39-win_amd64.pyd

编译后,将在当前路径下生成以下文件:

  • (1)build 文件夹:包含编译过程中的所有中间文件和最终的扩展模块库文件。
  • (2)使用 Cython 工具,将 .py 文件编译成 .c 文件:my_module.c
  • (3)编译后生成二进制 .pyc 文件:my_module.pyd

在这里插入图片描述

2.3、pyd 模块的导入与使用

# my_module.pydef hello():return "Hello, World!"def add(a, b):return a + bdef subtract(a, b):return a - b

同一个文件的py与pyd不要保存在一个路径下,否则无法区别是调用的py模块还是pyd模块。

# main.pyimport my_module  # 导入pyd模块print(my_module.hello())  # 输出: Hello, World!
print(my_module.add(1, 2))  # 输出: 3
print(my_module.subtract(1, 2))  # 输出: -1

四、(批量)将 .py 文件编译成 .pyd 文件(自动执行)

将批量 .py 文件编译成 .pyd 文件。

"""##############################################################
# 功能:将批量.py文件编译成.pyd文件。
##############################################################"""
import os
import glob
import shutildef py2pyd(one_all, del_py, paths):def compile_single_py(path):folder_path = os.path.dirname(path)  # 获取文件夹路径file_path = os.path.split(path)[1]  # 获取文件名(包括后缀)os.chdir(folder_path)  # 改变当前工作目录为 folder_path 所指定的目录############################################################################## 在在当前路径下,自动生成一个setup.py文件with open('setup.py', 'w') as f:f.write('from setuptools import setup\n')f.write('from Cython.Build import cythonize\n')f.write(f"setup(name='test', ext_modules=cythonize('{file_path}'))")# 开始编译setup.py(编译结束,将在当前路径下生成:xxx.cp38-win_amd64.pyd + xxx.c + build文件夹)os.system('python setup.py build_ext --inplace')#############################################################################filename = file_path.split('.py')[0]  # 获取文件名(没有后缀)pyd_name = f'{folder_path}\\{filename}.pyd'  # 获取.pyd文件路径# 若在当前路径下,已存在同名的.pyd文件,则删除。if os.path.exists(pyd_name):os.remove(pyd_name)"""修改.pyd文件名"""# 获取.pyd文件的文件名 ———— 如: xxx.cp38-win_amd64.pydamd64_pyd = glob.glob(filename + "*.pyd")  # glob.glob: 获取指定模式下的所有文件名列表print("*"*100)print(f"{amd64_pyd[0]} has been generated.")# 修改.pyd文件的文件名 ———— 如: xxx.pyd,即删除冗余的.cp38-win_amd64os.rename(amd64_pyd[0], pyd_name)  # os.rename(old_name, new_name): 将old_name重命名为new_name."""删除过程文件"""os.remove('setup.py')  # 删除自动生成的setup.py文件os.remove(f'{filename}.c')  # 删除自动生成的xxx.c文件shutil.rmtree(os.path.join(folder_path, 'build'))  # 删除自动生成的build文件夹及其所有内容。"""删除.py源文件 ———— 无法恢复,慎用!"""if del_py == 'del':os.remove(file_path)def get_all_file(path):"""遍历给定目录下的所有.py文件,包含子目录里的.py文件"""for root, dirs, files in os.walk(path):for name in files:if name.endswith(".py"):compile_single_py(os.path.join(root, name))if one_all == 'one':compile_single_py(paths)  # 若为单个.py文件,则直接执行。else:get_all_file(paths)       # 若为多个.py文件,则遍历所有文件,并单个执行。"""##############################################################
# 参数说明:
#         all:      批量编译指定目录及其子目录下的所有.py文件
#         one:      编译单个.py文件
#         del:      编译完成后删除源文件。注意:无法恢复,谨慎使用!
#         nodel:    编译完成后保留源文件。
##############################################################""""""##############################################################
# 示例1:批量编译指定目录及其子目录下的所有.py文件
#         py2pyd('all', 'nodel', r'D:\\PYTHON\\toPYD\\test')  # 不删除源文件
#         py2pyd('all', 'del', r'D:\\PYTHON\\toPYD\\test')  # 删除源文件
# 
# 示例2:编译单个.py文件
#         py2pyd('one', 'nodel', r'D:\\PYTHON\\toPYD\\test\\mycode.py')  # 不删除源文件
#         py2pyd('one', 'del', r'D:\\PYTHON\\toPYD\\test\\mycode.py')  # 删除源文件
##############################################################"""
if __name__ == '__main__':try:from setuptools import setup, Extensionfrom Cython.Build import cythonizepy2pyd('one', 'nodel', r'F:\py\pyinstaller\test.py')except ImportError:print("cython模块未安装,安装命令:pip install cython")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/20947.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

百度文心一言API批量多线程写文章软件-key免费无限写

百度文心大模型的两款主力模型ENIRE Speed、ENIRE Lite全面免费&#xff0c;即刻生效。 百度文心大模型的两款主力模型 这意味着&#xff0c;大模型已进入免费时代&#xff01; 据了解&#xff0c;这两款大模型发布于今年 3 月&#xff0c;支持 8K 和 128k 上下文长度。 ER…

Java集合面试题(概述,list,Map)

一个常见的"fail-safe"集合例子是CopyOnWriteArrayList。这个集合在每次修改时都会复制当前的数组&#xff0c;修改操作在新数组上进行&#xff0c;而遍历操作则在旧数组上进行。这样&#xff0c;即使在遍历过程中进行了修改&#xff0c;也不会影响遍历的进行。 插入…

车载诊断内容汇总(培训+视频)

车载诊断内容汇总 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗你的人和事&#xff0c…

pyopengl 立方体 正投影,透视投影

目录 顶点和线的方式 划线的方式实现: 顶点和线的方式 import numpy as np from PyQt5 import QtWidgets from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton from OpenGL.GL import * from OpenGL.GLU import * import sys…

Java大文件上传、分片上传、多文件上传、断点续传、上传文件minio、分片上传minio等解决方案

一、上传说明 文件上传花样百出&#xff0c;根据不同场景使用不同方案进行实现尤为必要。通常开发过程中&#xff0c;文件较小&#xff0c;直接将文件转化为字节流上传到服务器&#xff0c;但是文件较大时&#xff0c;用普通的方法上传&#xff0c;显然效果不是很好&#xff0c…

【Unity脚本】修改游戏对象的活动状态

【知识链】Unity -> Unity脚本 -> 游戏对象 -> 活动状态【摘要】本文介绍了如何通过编辑器和脚本来访问游戏对象的活动状态&#xff0c;并给出具体的场景示例。 文章目录 第一章 引言第二章 在编辑器中设置活动状态2.1. 在编辑器中设置活动状态2.1.1. 停用游戏对象2.…

文件IO(三)

文件IO&#xff08;三&#xff09; 左移右移Linux的man 手册文件IO打开文件操作文件关闭文件 caps lock开灯关灯读取按键文件IO操作目录文件打开目录文件操作目录文件 库动态库和静态库的优缺点创建静态库创建动态库 按下右ctrl键 亮灭灯 左移右移 Linux的man 手册 文件IO 打开…

FJSP:常春藤算法(Ivy algorithm,LVYA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

详细介绍 FJSP&#xff1a;常春藤算法&#xff08;Ivy algorithm&#xff0c;LVYA&#xff09;求解柔性作业车间调度问题&#xff08;FJSP&#xff09;&#xff0c;提供MATLAB代码-CSDN博客 完整MATLAB代码 FJSP&#xff1a;常春藤算法&#xff08;Ivy algorithm&#xff0c;…

图形学初识--多边形剪裁算法

文章目录 前言正文为什么需要多边形剪裁算法&#xff1f;前置知识二维直线直线方程&#xff1a;距离本质&#xff1a;点和直线距离关系&#xff1a; 三维平面平面方程距离本质&#xff1a;点和直线距离关系&#xff1a; Suntherland hodgman算法基本介绍基本思想二维举例问题描…

最小时间差

首先可以想到&#xff0c;可以计算出任意两个时间之间的差值&#xff0c;然后比较出最小的&#xff0c;不过这种蛮力方法时间复杂度是O(n^2)。而先将时间列表排序&#xff0c;再计算相邻两个时间的差值&#xff0c;就只需要计算n个差值&#xff0c;而排序阶段时间复杂度通常为O…

C语言实现贪吃蛇小游戏(控制台)

本篇主要内容是使用C语言在Windows环境的控制台中模拟实现经典小游戏贪吃蛇。 一、准备工作 我们要实现的基本功能有&#xff1a; 地图绘制蛇吃食物的功能&#xff08;上、下、左、右方向键控制蛇的动作&#xff09;蛇撞墙死亡蛇撞自身死亡计算得分蛇身加速、减速暂停游戏 …

9-Django项目--验证码操作

目录 templates/login/login.html utils/code.py views/login.py 验证码 生成验证码 code.py 应用验证码 views.py login.html templates/login/login.html {% load static %} <!DOCTYPE html> <html lang"en"> <head><meta charset&q…

PID算法入门

文章目录 122.12.22.3 344.14.24.3 1 e(t) 是偏差 实 和 目u(t) 是运算结果 2 层层叠加 得出完整的离散公式 2.1 kp 越大 系统偏差 减小的越快kp大的时候 会出现过冲现象&#xff1f; 0.5 那个会快他解释过冲 &#xff1a; 0.2的 5分钟正好到了 那0.5的五分钟 升的就比20多 就…

④单细胞学习-cellchat细胞间通讯

目录 1&#xff0c;原理基础 流程 受体配体概念 方法比较 计算原理 2&#xff0c;数据 3&#xff0c;代码运行 1&#xff0c;原理基础 原文学习Inference and analysis of cell-cell communication using CellChat - PMC (nih.gov) GitHub - sqjin/CellChat: R toolk…

在 JavaScript 中实现数据加密与解密:Web Cryptography API 与 CryptoJS详解

在 JavaScript 中&#xff0c;可以使用 Web Cryptography API 或第三方库如 crypto-js 来实现加密和解密。本文将介绍如何使用这两种方法在客户端进行数据的加密和解密。 使用 Web Cryptography API Web Cryptography API 是现代浏览器提供的一个强大、原生的加密 API。它允许…

关于留痕的使用常见的问题

1. 登录微信 登录要导出数据的微信&#xff08;不支持微信多开&#xff0c;不支持部分老版本微信&#xff09; 相关信息 想把手机端的微信聊天记录转移到电脑上可以使用微信自带的聊天记录迁移功能 操作步骤&#xff1a; 安卓&#xff1a; 手机微信->我->设置->聊…

[深度学习]使用python部署yolov10的onnx模型

测试环境&#xff1a; onnxruntime1.15.1 opencv-python4.8.0.76 部分实现代码&#xff1a; parser argparse.ArgumentParser()parser.add_argument("--model", typestr, default"yolov10n.onnx", help"Input your ONNX model.")parser.add_arg…

电子电器架构 --- 什么是域控制器?

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

美颜相机与美图秀秀的非会员图片保存技巧畅享专业级图像处理探索

美颜相机与美图秀秀的非会员图片保存技巧畅享专业级图像处理探索 今日对美颜相机和美图秀秀的深入使用中&#xff0c;我遇到了一些功能限制&#xff0c;特别是在尝试保存特定处理后的图片时&#xff0c;发现通常需要开通VIP会员才能享受完整服务。作为一名热衷于技术探索的爱好…

【数据结构】二叉树的层序遍历~动画超详解

目录 1 什么是层序遍历2 二叉树层序遍历的基本思路3 二叉树层序遍历的实现 1 什么是层序遍历 我们从字面意思就明白,所谓层序,就是一层一层按顺序去遍历一个二叉树,这和我们之前了解的按前中后序遍历方式完全不同 比方说这颗二叉树: 前序遍历: 层序遍历: 2 二叉树层序遍历的…