将 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 cythonize

setup(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.py

def hello():
    return "Hello, World!"

def add(a, b):
    return a + b

def subtract(a, b):
    return a - b

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

# main.py

import 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 shutil


def 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.pyd
        amd64_pyd = glob.glob(filename + "*.pyd")  # glob.glob: 获取指定模式下的所有文件名列表
        print("*"*100)
        print(f"{amd64_pyd[0]} has been generated.")
        # 修改.pyd文件的文件名 ———— 如: xxx.pyd,即删除冗余的.cp38-win_amd64
        os.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, Extension
        from Cython.Build import cythonize

        py2pyd('one', 'nodel', r'F:\py\pyinstaller\test.py')
    except ImportError:
        print("cython模块未安装,安装命令:pip install cython")

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

带交互的卡尔曼滤滤波|一维滤波|源代码

背景 一维卡尔曼滤波的MATLAB例程&#xff0c;​背景为温度估计。 代码介绍 运行程序后&#xff0c;可以自己输入温度真实值&#xff1a; 以20℃为例&#xff0c;得到如下的估计值​&#xff1a; 滤波前的值和滤波后的值分别于期望值&#xff08;真实值&#xff09;作差…

海光CPU:国产信创的“芯“动力解读

国产信创CPU-海光CPU CPU&#xff1a;信创根基&#xff0c;国之重器 国产CPU形成三大阵营&#xff1a;自主架构、x86及ARM。自主阵营中&#xff0c;龙芯和申威以LoongArch和SW-64为基石&#xff1b;ARM阵营由鲲鹏、飞腾主导&#xff0c;依托ARM授权研发处理器&#xff1b;x86阵…

Python知识点17---包

提前说一点&#xff1a;如果你是专注于Python开发&#xff0c;那么本系列知识点只是带你入个门再详细的开发点就要去看其他资料了&#xff0c;而如果你和作者一样只是操作其他技术的Python API那就足够了。 Python的包&#xff0c;你可以把它看成是一个大的模块&#xff0c;它…

【Java】javafx界面布局

目录 一、面板类 &#xff08;1&#xff09;Pane面板 &#xff08;2&#xff09;HBox面板 &#xff08;3&#xff09;VBox面板 &#xff08;4&#xff09;BorderPane面板 &#xff08;5&#xff09;FlowPane面板 (6)GridPane面板 &#xff08;7&#xff09;StackPane面…

生命在于学习——Python人工智能原理(3.1)

三、深度学习 &#xff08;一&#xff09;深度学习的概念 1、深度学习的来源 深度学习的概念来源于人工神经网络&#xff0c;所以又称深度神经网络。 人工神经网络主要使用计算机的计算单元和存储单元模拟人类大脑神经系统中大量的神经细胞&#xff08;神经元&#xff09;通关…

【精读文献】J. Environ. Manage.|青藏高原生态恢复项目下植被覆盖动态及其对生态系统服务的约束效应

目录 文章简介 01 文章摘要 02 研究背景、目标及创新点 2.1 研究背景 2.2 研究现状 03 研究区域与数据集 3.1 研究区域 3.2 研究数据 04 研究方法 4.1 趋势分析 4.2 残差趋势分析 4.3 偏相关 4.4 生态系统服务评价 4.5 约束线的定义和提取 05 研究结果 5.1 植被…

重学java 55. 集合 Set接口

我救自己万万次&#xff0c;铮铮劲草&#xff0c;绝不动摇 —— 24.6.2 一、Set集合介绍 Set和Map密切相关的 Map的遍历需要先变成单列集合&#xff0c;只能变成set集合 二、HashSet集合的介绍和使用 1.概述 HashSet是Set接口的实现类 2.特点 a、元素唯一 b、元素无序 c、无索引…

单元测试的心法分享

大家好&#xff0c;我是G探险者&#xff01; 今天我们简单聊聊单元测试的哪些事儿~ 两天时间我玩明白了单元测试的套路。 这里我分享一下思路。 在我眼里单元测试室什么&#xff1f; 请看这张草图&#xff1a; 单元测试主要关注单个代码单元&#xff08;通常是类或方法&am…

云原生架构案例分析_2.云原生技术助力某汽车公司数字化转型实践

名词解释&#xff1a; 互联网 在“互联网”模式下&#xff0c;我们仅仅把互联网看作是一种传播工具、传播手段、传播渠道和传播平台&#xff0c;对于互联网的应用大体上是在既有的运作逻辑的基础之上&#xff0c;把互联网作为延伸传媒影响力、价值和功能的一种延伸型工具&…

秒杀基本功能开发(不考虑高并发情况)

文章目录 1.显示秒杀状态1.controller修改GoodsController.java的toDetail方法&#xff0c;响应秒杀状态和秒杀剩余时间 2.前端1.goodsDetail.html 图片下面添加一行秒杀开始时间2.goodsDetail.html 添加计时器js代码 3.测试1.秒杀进行中2.修改db的秒杀开始时间为明天3.出现秒杀…

msvcr120.dll是干嘛的?出现找不到msvcr120.dll丢失怎样解决

msvcr120.dll是Microsoft Visual C 2012 Redistributable的核心文件&#xff0c;它是Microsoft Corporation开发的C/C运行时库文件之一。这个文件通常与应用程序一起安装&#xff0c;为应用程序提供许多基本的运行时功能&#xff0c;包括内存管理、异常处理、输入/输出操作等。…

Jenkins、GitLab部署项目

1、安装JDK 1.1、下载openJdk11 yum -y install fontconfig java-11-openjdk1.2、查看安装的版本号 java -version1.3、配置环境变量 vim /etc/profile在最底部添加即可 export JAVA_HOME/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64 export PATH$JAVA_HOME/…

SpringBoot注解--10--@Bean,对象注入的三种方法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Bean一、如何使用方法注解注意Bean 的命名规则&#xff0c;当没有设置 name 属性时&#xff0c;那么 bean 默认的名称就是方法名&#xff0c;当设置了 name 属性之后…

【OJ】C++ | 二叉树进阶 · 合集(2)

摘要&#xff1a;根据二叉树创建字符串、二叉树的最近公共祖先、二叉树的层序遍历 前言&#xff1a;承接上文&#xff0c;本文继续提供二叉树进阶有关题目的解法。如有错误&#xff0c;烦请指正。 目录 1. 根据二叉树创建字符串 题解及代码 2. 二叉树的最近公共祖先 题解及…

PHAR反序列化

PHAR PHAR&#xff08;PHP Archive&#xff09;文件是一种归档文件格式&#xff0c;phar文件本质上是一种压缩文件&#xff0c;会以序列化的形式存储用户自定义的meta-data。当受影响的文件操作函数调用phar文件时&#xff0c;会自动反序列化meta-data内的内容,这里就是我们反序…

2024年06月编程语言流行度排名

点击查看最新编程语言流行度排名&#xff08;每月更新&#xff09; 2024年06月编程语言流行度排名 编程语言流行度排名是通过分析在谷歌上搜索语言教程的频率而创建的 一门语言教程被搜索的次数越多&#xff0c;大家就会认为该语言越受欢迎。这是一个领先指标。原始数据来自…

JAVA和爬虫,那个值得学习

如果你是初学者&#xff0c;建议先从基础的编程语言学起&#xff0c;比如Java&#xff0c;它能为你打下坚实的编程基础&#xff0c;并且在未来转学其他语言或技术时更加容易。随着编程基础的建立&#xff0c;你可以根据自己的兴趣或职业规划&#xff0c;学习爬虫技术作为补充技…

使用python下载股票数据至sqlite数据库

代码下载地址&#xff1a; https://download.csdn.net/download/weixin_44600457/89389489

961题库 北航计算机 计算机网络 附答案 选择题形式

有题目和答案&#xff0c;没有解析&#xff0c;不懂的题问大模型即可&#xff0c;无偿分享。 第1组 习题 OSI 参考模型的第 5 层( 自下而上 ) 完成的主要功能是 A. 差错控制 B. 路由选择 C. 会话管理 D. 数据表示转换 100BaseT 快速以太网使用的导向传输介质是 A. 双绞线 B. …

德人合科技——@天锐绿盾 | -文档透明加密系统

天锐绿盾文档透明加密系统是一种先进的数据安全解决方案&#xff0c;旨在保护企业和组织的敏感信息&#xff0c;防止未经授权的访问和泄漏。 PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 以下是该系统的一些关键特点和功…