打包
python原创工具大约 4 分钟约 1261 字
代码补全
pip install pyreadline
安装模块后,在python命令行模式通过tab键可以代码补全
生成C程序
安装环境
pip install Cython
python实例代码
def fib(n):
return 1 if n ==1 or n == 2 else fib(n - 1) + fib(n - 2)
setup.py配置
from setuptools import setup
from Cython.Build import cythonize
# 打包whl:python3 setup.py bdist_wheel
# 生成C文件:python3 setup.py build_ext --inplace
setup(
ext_modules=cythonize('test/*.py'))
生成C文件
python3 setup.py build_ext --inplace
生成whl
python3 setup.py bdist_wheel
使用
import time
from fib import fib
start = time.time()
result = fib(20)
end = time.time()
print('斐波那契数列第20项为'+ str(result)+'耗时:'+str(end - start)+'秒')
Cython打包py文件,生成包含pyd的wheel
windows平台
setup.py文件配置
from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
from pathlib import Path
import shutil
class MyBuildExt(build_ext):
def run(self):
build_ext.run(self)
build_dir = Path(self.build_lib)
root_dir = Path(__file__).parent
target_dir = build_dir if not self.inplace else root_dir
self.copy_file(Path('demo') / '__init__.py', root_dir, target_dir)
def copy_file(self, path, source_dir, destination_dir):
if not (source_dir / path).exists():
return
shutil.copyfile(str(source_dir / path), str(destination_dir / path))
setup(
name="MyModule",
ext_modules=cythonize(
[
Extension("demo.*", ["demo/*.py"])
],
build_dir="build",
compiler_directives=dict(
always_allow_keywords=True
)),
cmdclass=dict(
build_ext=MyBuildExt
),
packages=[],
)
linux平台
from setuptools import setup
from setuptools.extension import Extension
from Cython.Build import cythonize
from Cython.Distutils import build_ext
setup(
name="MyModule" # 模块名称 import MyModule,
ext_modules=cythonize(
[
Extension("pkg1.*", ["root/pkg1/*.py"]),
Extension("pkg2.*", ["root/pkg2/*.py"]),
Extension("1.*", ["root/*.py"])
],
build_dir="build",
compiler_directives=dict(
always_allow_keywords=True
)),
cmdclass=dict(
build_ext=build_ext
),
packages=["pkg1", "pkg2"] # packages=[]时打包后的wheel文件中不含源码(.py)
)
打包多个模块
# -*- coding: UTF-8 -*-
from setuptools import setup
from Cython.Distutils import build_ext
from Cython.Build import cythonize
from pathlib import Path
import shutil
class MyBuildExt(build_ext):
def run(self):
build_ext.run(self)
build_dir = Path(self.build_lib)
root_dir = Path(__file__).parent
target_dir = build_dir if not self.inplace else root_dir
self.copy_file(Path('sample') / '__init__.py', root_dir, target_dir)
def copy_file(self, path, source_dir, destination_dir):
if not (source_dir / path).exists():
return
shutil.copyfile(str(source_dir / path), str(destination_dir / path))
setup(
name="sample",
ext_modules=cythonize(["sample/*.py","sample/test/*.py"], annotate=True,
build_dir="build",
compiler_directives=dict(
always_allow_keywords=True
)),
cmdclass=dict(
build_ext=MyBuildExt
),
# include_dirs=[np.get_include()] ,
packages=[],
)
修改cython文件
- 文件目录:
cython\Compiler\ModuleNode.py
- 原文件内容
code.putln(header2)
code.putln("#else")
code.putln("%s CYTHON_SMALL_CODE; /*proto*/" % header3)
- 替换内容
if self.scope.is_package:
code.putln("#if !defined(CYTHON_NO_PYINIT_EXPORT) && (defined(WIN32) || defined(MS_WINDOWS))")
code.putln("__Pyx_PyMODINIT_FUNC init__init__(void) { init%s(); };" % env.module_name)
code.putln("#endif")
code.putln(header2)
code.putln("#else")
code.putln("%s CYTHON_SMALL_CODE; /*proto*/" % header3)
if self.scope.is_package:
code.putln("#if !defined(CYTHON_NO_PYINIT_EXPORT) && (defined(WIN32) || defined(MS_WINDOWS))")
code.putln("__Pyx_PyMODINIT_FUNC PyInit___init__(void) { return %s(); };" % (
self.mod_init_func_cname('PyInit', env)))
code.putln("#endif")
生成文件
python setup.py bdist_wheel
生成pyc文件
生成单个pyc文件
python -m py_compile /path/to/example.py #需要提供py文件绝对路径
生成整个目录的pyc文件
compile_dir(dir[, maxlevels[, ddir[, force[, rx[, quiet]]]]])
参数含义:
– maxlevels:递归编译的层数
– ddir:If ddir is given, it is prepended to the path to each file being compiled for use in compilation time tracebacks, and is also compiled in to the byte-code file, where it will be used in tracebacks and other messages in cases where the source file does not exist at the time the byte-code file is executed.
– force:如果True,不论是是否有pyc,都重新编译
– rx:一个正则表达式,排除掉不想要的目录
– quiet:如果为True,则编译不会在标准输出中打印信息
python -m compileall <dir>
打包python项目生成pyc
import argparse
import datetime
from pathlib import Path
import os
import shutil
import compileall
def main():
parser = argparse.ArgumentParser() # 获取项目的parameters
parser.add_argument("src", type=Path)
args = parser.parse_args()
root = args.src # 根目录
for src_file in root.rglob("*.pyc"): # 先删除根目录下的pyc文件
os.remove(src_file)
compileall.compile_dir(root, force=True) # 将项目下的py都编译成pyc文件
current_day = datetime.date.today() # 当前日期
edition = "1.1.2" # 设置版本号
dest = root.parent / f"{root.name}_{edition}.{'001'}_beta_{current_day}" # 目标文件夹名称
for src_file in root.glob("**/*.pyc"): # 遍历所有pyc文件
relative_path = src_file.relative_to(root) # pyc文件对应模块文件夹名称
dest_folder = dest / str(relative_path.parent.parent) # 在目标文件夹下创建同名模块文件夹
os.makedirs(dest_folder, exist_ok=True)
dest_file = dest_folder / (src_file.stem.rsplit(".", 1)[0] + src_file.suffix) # 创建同名文件
print(f"install {relative_path}")
shutil.copyfile(src_file, dest_file) # 将pyc文件复制到同名文件
if __name__ == '__main__':
main()
python3 pack_pyc.py 目录
python打包可执行文件
环境安装
pip install nuitka
编译
nuitka --mingw64 --standalone --output-dir=out --enable-plugin=pyqt5 --show-progress --windows-company-name=Test --windows-product-name=Test --windows-product-version=1.0.0 --onefile --include-package=qt_material --include-data-dir=qt_material=qt_material dialog.py
参数
--include-data-dir=qt_material=qt_material:数据目录
--windows-disable-console #不显示控制台窗口
--windows-icon=ICON_PATH #添加ico
--nofollow-imports # 所有的import不编译,交给python3x.dll执行
--follow-import-to=need #need为你需要编译成C/C++的py文件夹命名
--mingw64 #mingw(官方建议编译器)
--standalone #独立环境,这是必须的(否则拷给别人无法使用)
--windows-disable-console #没有CMD控制窗口
--output-dir=out #生成文件路径
--show-progress #显示编译的进度,很直观
--show-memory #显示内存的占用
--include-qt-plugins=sensible,styles #打包后PyQt的样式就不会变了
--plugin-enable=qt-plugins #需要加载的PyQt插件
--plugin-enable=tk-inter #打包tkinter模块的刚需
--plugin-enable=numpy #打包numpy,pandas,matplotlib模块的刚需
--plugin-enable=torch #打包pytorch的刚需
--plugin-enable=tensorflow #打包tensorflow的刚需
--windows-uac-admin=Windows #用户可以使用管理员权限来安装
--onefile #打包成单个exe文件
pyinstaller打包
参数
- 添加数据文件
--add-data "D:\\Program Files\\Python36\\Lib\\site-packages\\qt_material\\;qt_material"
- 不显示控制台窗口
-w
- 打包独立文件
-F