工具

  • cython
  • mypyc

    • 使用带 annotation 类型注解 的 .py 文件,编译制作 .so 文件
    • 速度提升

      • 约十倍
    • 注意

      • mypy 类型检查出错,可能编译不能通过,或者导致编译的程序有问题
      • 因此,最好 mypy 检查无错误,无警告

优化字节码文件 .pyc Vs. .pyo

  • .pyc 和 .pyo 文件

    • .pyo 只能被直接执行,不能被导入
    • .pyo 优化等级更高

制作方法

  • 通过脚本个性化编译

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    import py_compile
    
    """
    参数如下:
    file:要编译的py文件
    cfile:编译之后的字节码文件,不指定的话默认为源文件目录下的__pycache__目录的下的'源文件名.解释器类型-python版本.字节码类型'文件
    dfile:错误消息文件,默认和cfile一样,一般不用管
    doraise:是否开启异常处理,默认和False
    optimize:优化字节码级别。如果是pyc:可以选-1或0。pyo的话,可以选1或2。都是值越小优化程度越高
    """
    py_compile.compile(file="test.py", cfile=r"./test.pyc", optimize=-1)
    py_compile.compile(file="test.py", cfile=r"./test.pyo", optimize=1)
  • 命令行快速编译

    1
    2
    3
    4
    5
    6
    7
    8
    
    # 编译成pyc
    python -m py_compile 源代码
    
    # 编译成pyo
    python -O -m py_compile 源代码
    
    # 如果需要编译整个目录内的所有源代码
    python compileall

.pyd 与 .dll 文件

  • 来源不同

    • .pyd 通过 .py 文件制作

      • 可以直接导入
    • .dll 通过 c 和 c++ 编写

      • 使用 ctypes 进行加载
    • 注意:

      • 在 linux 上 它们两者都是以 .so 为后缀的文件
  • 实例

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    # to_pyd.py
    # 导入模块
    import Cython.Build
    
    # 传入要编译成pyd的py文件
    ext = Cython.Build.cythonize("test_v.py")
    
    # 下面还要导入另一个模块
    import distutils.core
    
    # 调用setup方法
    distutils.core.setup(
    ext_modules=ext,  # 将Cython.Build.cythonize返回的结果传进去
    )
    • 命令行运行

      1
      
      $ python to_pyd.py build

原位编译

1
cythonize -i <your_file.py>
  • 参数

    • -i

      • inplace, 原位生成 pyd 或 .so 文件
    • -a

      • 制作 html 文档文件

放置暴露变量

  • $__all__$ 不能用来强制保密

    • 只是 用来放置 from your_module import * 导入过多的变量
    • 但是,这些变量依然能够被导入

      1
      2
      3
      4
      
      # module hello.py
      __all__ = ['a']
      a = 1
      b = 2
      1
      2
      3
      4
      
      # Use hello.py module
      from hello import *
      print(a)  # OK
      print(b)  # Failed
      1
      2
      3
      
      from hello import a, b
      print(a)  # OK
      print(b)  # OK