Python编译成C

Python编译成C

参考文章:https://blog.csdn.net/sinat_28375239/article/details/108265559

参考文章:https://blog.csdn.net/fu6543210/article/details/90770794

参考文章:https://iowiki.com/jython/jython_overview.html

参考文章:https://blog.csdn.net/weixin_45530440/article/details/123531932

参考文章:https://zhuanlan.zhihu.com/p/454377119

python 是一门解释型语言,效率与编译型语言比效率较低;python 解释器使用最广泛的是Cpython使用 C 语言开发的 python 解释器;当我们对效率具有一定要求的时候可以将python代码编译成为 C;

1.解释器的介绍

Python 解释器最常见的是Cpython, 之所以使用CPython这个词,是因为Python还有一些其它的实现,比如Jython,就是Java版的Python,还有烧脑的PyPy,使用 Python 再把 Python 实现了一遍。由于整个 Python 语言从规范到解释器都是开源的,所以理论上,只要水平够高,任何人都可以编写 Python 解释器来执行 Python 代码(当然难度很大)。事实上,确实存在多种 Python 解释器;

1.1 Cpython

CPython 是特指 C 语言实现的Python,就是原汁原味的Python。

当我们编写 python 代码的时候,我们得到以.py为扩展名的文件,运行代码的时候是需要 Python 解释器去解释执行.py文件。

当我们从 Python 官方网站下载并安装好 Python 3.x后,我们就直接获得了一个官方版本的解释器:CPython。这个解释器是用C语言开发的,所以叫CPython。在命令行下运行 python 就是启动CPython解释器。CPython是使用最广的Python解释器。

Cython 语言是 Python 的一个超集,编译成C语言,产生的性能提升可以从几个百分点到几个数量级,具体取决于手头的任务。 对于受Python原生对象类型约束的工作,加速将不会很大。 但是对于数值操作,或任何不涉及 Python 自身内部的操作,收益可能是巨大的。

1.2 Jpython

Jython(原 JPython),是一个用 Java 语言写的 Python 解释器。Jython 程序可以和 Java 无缝集成。除了一些标准模块,Jython 使用 Java 的模块。

Jython 是 Python 编程语言的 JVM 实现。 它旨在在Java平台上运行。 Jython程序可以导入和使用任何Java类。 就像Java一样,Jython程序编译为bytecode 。 其中一个主要优点是用Python设计的用户界面可以使用AWTSwingSWT Package GUI元素。

以下是Python和Jython之间的区别 :

  • Python 的参考实现,称为 CPython,是用 C 语言编写的。 另一方面,Jython 完全用 Java 编写,是一个 JVM 实现。
  • 标准 Python 可在多个平台上使用。 Jython 适用于安装了 JVM 的任何平台。
  • 标准 Python 代码编译为.pyc文件,而 Jython 程序编译为.class文件。
  • Python 扩展可以用 C 语言编写。 Jython 的扩展是用 Java 编写的。
  • Jython 本质上是真正的多线程。 然而,Python使用Global Interpreter Lock (GIL)机制来实现此目的。
  • 两种实现都有不同的垃圾收集机制。

1.3 pypy

Pypy 是用 Python 自身实现的解释器。针对 CPython 的缺点进行了各方面的改良,性能得到很大的提升。最重要的一点就是Pypy集成了JIT(即时编译)。但是,Pypy无法支持官方的C/Python API,导致无法使用例如Numpy,Scipy等重要的第三方库。这也是现在Pypy没有被广泛使用的原因。

PyPy 使用了JIT(即时编译)技术,混合了动态编译和静态编译的特性,仍然是一句一句编译源代码,但是会将翻译过的代码缓存起来以降低性能损耗。相对于静态编译代码,即时编译的代码可以处理延迟绑定并增强安全性。绝大部分 Python 代码都可以在 PyPy 下运行,但是 PyPy 和 CPython 有一些是不同的。

2.编译Python到C

Python 代码可以直接调用 C 模块。这些 C 模块可以是通用的 C 库或专门为 Python 工作的库。Cython 生成第二种类型的模块:与Python 内部对话的 C 库,可以与现有的 Python 代码绑定在一起。

Cython 代码在设计上看起来很像 Python 代码。如果你给 Cython 编译器提供了一个Python程序,它将会按原样接受它,但是 Cython 的原生加速器都不会起作用。但是如果你用 Cython 的特殊语法来修饰 Python 代码,那么 Cython 就可以用快速的 C 代替慢的 Python 对象。

2.1 python 文件编译为C文件

  • 安装

    pip install cpython
    pip install cython
    
  • 使用

    创建.pyx文件,将 python 的代码写入文件中;创建setup.py文件,这两个文件都在同一文件夹下面;

    # code.pyx
    def main():
        print("+"*13,"执行开始","+"*13)
        print("666666666666666")
        print("+"*13,"执行结束","+"*13)
    
    
    main()
    

    编写setup.py

    # setup.py
    
    from setuptools import setup
    from Cython.Build import cythonize
    
    # 编译 pyx 文件;
    setup(ext_modules=cythonize('code.pyx'))
    

    在终端中执行该文件

    python setup.py build_ext --inplace
    

    执行完成之后会在同级目录下面产生code.c的文件,unix系统可能会产生的是.so

    用参数build_ext运行setup.py时,Cython会查找cythonfn.pyx并构建code.so

    --inplace参数让 Cython 在当前目录中构建编译模块,而不是在一个独立的构建目录中。在构建完成后,会得到中间文件cythonfn.ccode.so

  • .pyx介绍

    pyx 文件是由 Cython 编程语言 编写 而成的 Python 扩展模块源代码文件。.pyx 文件要想被 python 语言直接识别,必须先被编译成 .c 文件,再编译成 .pyd .so文件,才可作为模块import直接导入使用。

2.2 多文件编译

把一个目录下所有python源文件编译pyc;这种形式的编译是直接编译成为二进制文件,与C 不同;

一般来说,我们的工程都是在一个目录下的,一般不会说仅仅编译一个py文件而已,而是需要把整个文件夹下的py文件都编译为pyc文件,python又为了我们提供了另一个模块:compileall 。使用方法如下:

python -m compileall ./路径

编译完成后如果想要直接运行Pyc文件注意两点:要把pyc文件从pycache目录中移动出来,放到py文件对应的位置

修改pyc文件名,生成的pyc文件的文件名一般为.cpython-36.pyc。pyc 文件可以和 py 文件一样用 import 导入,但是在此之前需要将pyc 文件重命名;

# 例如对 model.py 生成的pyc文件为 model.cpython-36.pyc

# 如果现在想导入model.cpython-36.pyc,直接用

import model

# >>> 会报错ImportError: No module named 'model'

# 需要将model.cpython-36.pyc重命名为model.pyc

注意:
compileall.compile_path(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=-1)

字节编译沿 sys.path 找到的所有.py文件。如果所有文件都已成功编译,则返回true值,否则返回false值。

如果 skip_curdirtrue(默认值),则当前目录不包括在搜索中。所有其他参数传递到 compile_dir() 函数。注意,与其他编译函数不同,maxlevels 默认为 0。

pyc文件就是 Python 程序编译后得到的字节码文件 (py->pyc).

posted @ 2022-12-31 10:38  紫青宝剑  阅读(1576)  评论(0编辑  收藏  举报