如何从多个脚本构建一个单一的Python文件?
我有一个简单的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 个回答
使用 stickytape 模块
stickytape scripts/blah --add-python-path . > /tmp/blah-standalone
这样做会得到一个可以运行的脚本,但不一定容易让人看懂。
我发现这个很有用:
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
我想出了一个解决方案,涉及到模块查找器、编译器和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)