如何从多个脚本构建一个单一的Python文件?

53 投票
8 回答
71974 浏览
提问于 2025-04-17 11:03

我有一个简单的Python脚本,它会导入我写的其他模块等等。由于我的环境原因,我的PYTHONPATH比较长。而且我使用的是Python 2.4。

我需要做的是把我的脚本和所有不属于标准Python的依赖项打包,这样我就可以把一个文件通过邮件发送到另一个系统,在那里我想执行它。我知道目标Python版本是一样的,但目标系统是Linux,而我在Windows上。否则我就可以直接用py2exe了。

理想情况下,我希望发送一个.py文件,这个文件能把所有需要的模块都嵌入进去,但我也能接受自动生成一个zip文件,我只需要解压缩,里面包含所有需要的模块,放在一个目录里。

我看过各种打包解决方案,但似乎找不到合适的方法来实现这个目标。我是不是漏掉了什么?

[编辑] 我似乎对我想要的东西不太清楚。我基本上是在寻找类似py2exe的工具,它能从给定的Python脚本生成一个文件(或两个文件),自动包含所有导入的模块。

例如,如果我有以下两个文件:

[\foo\module.py]
def example():
    print "Hello"

[\bar\program.py]
import module
module.example()

然后我运行:

cd \bar
set PYTHONPATH=\foo
program.py

那它就能正常工作。我想要的是能够说:

magic program.py

最后得到一个文件,或者一个文件和一个zip文件,这样我就可以把它复制到Linux上运行。我不想在目标Linux系统上安装我的模块。

8 个回答

17

使用 stickytape 模块

stickytape scripts/blah --add-python-path . > /tmp/blah-standalone

这样做会得到一个可以运行的脚本,但不一定容易让人看懂。

65

我发现这个很有用:

http://blog.ablepear.com/2012/10/bundling-python-files-into-stand-alone.html

简单来说,你可以把你的模块打包成一个.zip文件,并在里面放一个__main__.py文件,这样你就可以像下面这样运行它:

python3 app.zip

因为我的应用程序很小,所以我在我的主脚本和__main__.py之间做了一个链接。

补充说明:

你还可以通过在文件顶部添加一行代码,让这个zip文件在类Unix系统上变得可执行。这对于使用Python3的脚本可能很重要。

echo '#!/usr/bin/env python3' | cat - app.zip > app
chmod a+x app

这样就可以在不指定python的情况下直接执行了。

./app
1

我想出了一个解决方案,涉及到模块查找器、编译器和zip函数,这个方法效果不错。可惜我不能把完整的程序贴在这里,因为它和其他无关的代码混在一起了,不过我可以分享一些代码片段:

zipfile = ZipFile(os.path.join(dest_dir, zip_name), 'w', ZIP_DEFLATED)
sys.path.insert(0, '.')
finder = ModuleFinder()
finder.run_script(source_name)

for name, mod in finder.modules.iteritems():
    filename = mod.__file__
    if filename is None:
        continue
    if "python" in filename.lower():
        continue

    subprocess.call('"%s" -OO -m py_compile "%s"' % (python_exe, filename))

    zipfile.write(filename, dest_path)

撰写回答