如何从多个脚本构建单个python文件?

时间:2012-01-25 11:54:20

标签: python

我有一个简单的python脚本,它导入我编写的各种其他模块(等等)。由于我的环境,我的PYTHONPATH很长。我也在使用Python 2.4。

我需要做的是以某种方式打包我的脚本和所有不属于标准python的依赖项,以便我可以将单个文件通过电子邮件发送到我想要执行它的另一个系统。我知道python的目标版本是相同的,但它在linux上,我在Windows上。否则我只使用py2exe。

理想情况下,我想发送一个.py文件,以某种方式嵌入所有必需的模块,但我决定自动构建一个zip,我可以解压缩,所需的模块都在一个目录中。

我已经看过各种包装解决方案,但我似乎无法找到合适的方法。我错过了什么吗?

[编辑]我似乎很不清楚我在追求什么。我基本上都在寻找像py2exe这样的东西,它会从给定的python脚本生成一个文件(或2个文件),自动包含所有导入的模块。

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

[\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 个答案:

答案 0 :(得分:31)

我觉得这很有用:

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 :(得分:8)

使用stickytape模块

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

答案 2 :(得分:8)

您可以尝试将脚本转换为可执行文件。 首先,使用:

pip install pyinstaller

安装后类型(确保您在感兴趣的文件目录中):

pyinstaller --onefile --windowed filename.py

这将创建包含所有必需模块的脚本的可执行版本。然后,您可以将此可执行文件传输(复制并粘贴)到要运行脚本的PC或计算机上。

我希望这会有所帮助。

答案 3 :(得分:4)

您应该创建一个egg文件。这是python文件的存档。

请参阅此问题以获取指导:How to create Python egg file

答案 4 :(得分:0)

您是否考虑过分发官方包装解决方案Automatic script creation

您所做的是create a setup.py为您编程并提供将转换为您可以运行的可执行文件的入口点。这样您就不必更改源布局,同时仍然可以轻松地分发和运行程序。

您可以在gunicorn's setup.py

中找到有关此系统的真实应用的示例

答案 5 :(得分:0)

发送单个.py的唯一方法是,如果将所有各种模块中的代码移动到单个脚本中,并且您必须重做所有内容以引用新位置。

更好的方法是将有问题的模块移动到与命令相同的目录下的子目录中。然后,您可以确保包含该模块的子目录具有导入主模块文件的__init__.py。那时你可以通过它来引用事物。

例如:

应用程序目录:/test

模块目录:/test/hello

/test/hello/__init__.py内容:

import sayhello

/test/hello/sayhello.py内容:

def print_hello():
    print 'hello!'

/test/test.py内容:

#!/usr/bin/python2.7

import hello

hello.sayhello.print_hello()

如果您运行/test/test.py,您将看到它从现有目录下的模块目录运行print_hello函数,不需要更改PYTHONPATH

答案 6 :(得分:0)

如果要将脚本及其所有依赖项打包到一个文件中(它不是.py文件),您应该查看virtualenv。这是一个工具,允许您构建沙箱环境以安装Python包,并管理所有PATH,PYTHONPATH和LD_LIBRARY_PATH问题,以确保沙箱完全自包含。

如果您从没有安装其他库的原始Python开始,然后easy_install您的依赖项进入虚拟环境,您将最终在virtualenv中构建一个只需要运行Python的项目。

沙箱是目录树,而不是单个文件,但是对于分发,您可以对其进行tar / zip。我从未尝试过分发env所以可能存在路径依赖,我不确定。

您可能需要分发构建脚本,以在目标计算机上构建虚拟环境。 zc.buildout是一个帮助自动执行该过程的工具,有点像与Python包系统和PyPI紧密集成的“make install”。

答案 7 :(得分:0)

我提出了一个涉及modulefinder,编译器和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)