
大家好,欢迎来到 Crossin 的编程教室。
几乎所有Python学习者都想过的这样一个问题:
怎样才能把自己刚写好的超级无敌狂拽酷炫吊炸天的代码发给别人玩玩呢?
不同于c++代码可以直接编译成可执行的exe文件,或者js代码在浏览器中就能执行,Python代码必须通过Python解释器来运行,而这是很多操作系统都没有预装的。

因此,想向“麻瓜”朋友展示你的“魔法”,很简单,先偷偷在他电脑上安装好python……

如果这招行不通,你还有个选择,就是通过工具将Python代码打包成可独立执行的exe文件。
打包Python代码的工具有很多,你常用的是哪个?
我在以前的视频中讲过如何将一个Python游戏打包成exe:
这里用的是pyinstaller。
不过当时有不少人都提到另一个名字:nuitka。
好好好,今天我就来讲讲,如何用nuitka打包Python程序,以及它的一些隐藏功能。
pip install nuitkapip install 安装,完成后就可以通过 nuitka + 要打包的代码文件名进行打包。
nuitka 你的程序.py
不过这样打包好的exe文件仍然无法在没装Python的电脑上运行。
我们还得在打包时加上参数 --standalone ,这样才会将Python解释器和目标代码的所有依赖都打包进去:
nuitka 你的程序.py --standalone参数 --onefile 则是将所有文件打包成一个单独的可执行文件:
nuitka 你的程序.py --standalone --onefile打包后的exe程序可以在没有安装Python的同类系统上运行。而且,即便是在win7下打包的程序,拿到win10上也能运行。
诶,反过来就不一定哦,你知道为什么吗?

下面再来试试之前我写的羊了个羊Python版,看看nuitka对于更复杂的GUI程序和第三方库支持得如何。
在打包前,首先还是要确认你的程序可以正常执行。
然后按照刚才的方法打包。但是,出错了。

看报错是缺少了一个icon.png的图片。这个问题我们上次就遇到过,是因为pgzero要用到一个图标文件。
解决办法就是把文件路径加到打包参数里,格式是:
nuitka 你的程序.py --standalone --include-data-files=电脑上资源文件的路径=程序中的调用路径如果你找不到pgzero模块中的这个文件,也可以随便找张图片作为替代,只要路径正确就可以。
游戏代码中使用到的外部资源还有images文件夹里的图片,和music文件夹中的音乐音效。同样也需要导入打包。对于整个文件夹资源的导入可以使用 --include-data-dir 参数,设定路径的规则跟刚才一样。
例如:
nuitka --standalone --onefile \
--include-data-files=icon.png=pgzero/data/icon.png \
--include-data-dir=images=images \
--include-data-dir=music=music \
sheep.py设定好后再次打包,等待完成之后,就可以通过生成的exe文件来运行游戏啦

我们虽然没有告诉nuitka要打包哪些模块,但因为设定了--standalone,它自动会找到程序依赖的模块打包进去。
而且打包后的程序在执行出错时,也可以准确地给出错误提示。这点在实用中非常重要。
除此之外,nuikta其实还有个隐藏功能--给代码加速。
比如这样一份带有大量数学计算的代码:
import time
from typing import List
def complex_computation(n: int) -> List[float]:
start_time = time.time()
"""
一个计算密集型的函数,进行大量数学运算
包含:循环、浮点运算、列表操作等
"""
result = []
for i in range(n):
temp = 0.0
for j in range(n):
temp += (i * j) / (j + 1) ** 2
temp = temp ** 0.5
if j % 2 == 0:
temp = temp * 1.5
else:
temp = temp * 0.7
result.append(temp)
if i % 1000 == 0:
execution_time = time.time() - start_time # 计算执行时间
print(i, f"{execution_time:.2f}")
return result
def main():
n = 10000 # 执行次数
start_time = time.time() # 记录开始时间
result = complex_computation(n) # 执行计算密集型操作
execution_time = time.time() - start_time # 计算执行时间
print(f"执行时间: {execution_time:.2f} 秒")
if __name__ == "__main__":
main()我们来对比一下直接运行、pyinstaller打包后运行、nuikta打包后运行的耗时:

可以看到,用pyinstaller打包后运行的耗时跟直接运行差不多,但用nuikta打包后则要快不少。
之所以会出现这样的效果,是因为nuitka的原理并不同于其他的打包工具。像cx_freeze、pyinstaller,都是将python解释器和目标代码及其依赖项打包在一起,生成可执行文件。
而nuitka是将Python代码转成C代码,再通过C编译器编译出机器码并优化。所以,更准确来说,nuitka是将python代码编译成可执行文件,而不仅仅是字面意义的打包。

因此对于有大量CPU计算的Python代码,nuitka打包后会有明显的速度提升。
除了打包成可以在windows系统上运行的exe文件,nuitka还支持其他平台,比如在苹果电脑上打包成.app应用程序。这时候就需要加上参数 --macos-create-app-bundle,并可用 --macos-app-icon 指定程序的图标文件。
nuitka提供了很多这样的打包参数,让你更精准控制打包出来的程序效果。用 nuitka --help 命令可以查看所有参数,但它的参数实在也太多了。

幸好,已经有大手子做了nuitka的辅助工具,比如这个NuitkaGUI,就可以让你通过可视化的选项,傻瓜式地设定打包参数,将nuitka的使用体验又拉高了一个档次。

总结一下:
但还是要提醒,任何Python打包工具都不是万能的,难免会有出错的情况,nuitka也不例外。如果你的代码总是打包失败,那么不妨换其他工具试一试,或许就能解决。
如果本文对你有帮助,欢迎点赞、评论、转发。你们的支持是我更新的动力~
感谢转发和点赞的各位~
本文分享自 Crossin的编程教室 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!