仅将python脚本作为可执行文件发送
我刚刚写了一个python脚本,我想把它发送给一个朋友,这样他们就可以使用它了。我想知道如何把它打包成一个“程序”,他们可以随时运行,而不需要访问代码本身 更好的是,我应该寻找什么?关于如何做到这一点的说明将有所帮助,但我也想知道我可以搜索什么来获得更多信息仅将python脚本作为可执行文件发送,python,python-3.x,scripting,Python,Python 3.x,Scripting,我刚刚写了一个python脚本,我想把它发送给一个朋友,这样他们就可以使用它了。我想知道如何把它打包成一个“程序”,他们可以随时运行,而不需要访问代码本身 更好的是,我应该寻找什么?关于如何做到这一点的说明将有所帮助,但我也想知道我可以搜索什么来获得更多信息 此外,这将从unix计算机传输到unix计算机。Python支持可执行归档。这是一种将一个程序和一组模块封装到单个文件中的方法。例如,youtube dl是这样分发的 请注意,“可执行文件”基本上只是一个带有#的zip文件-前面一行。所以一
此外,这将从unix计算机传输到unix计算机。Python支持可执行归档。这是一种将一个程序和一组模块封装到单个文件中的方法。例如,
youtube dl
是这样分发的
请注意,“可执行文件”基本上只是一个带有#的zip文件代码>-前面一行。所以一个知识渊博的人仍然可以获得源代码
在UNIX上,使用zip
在Makefile
中轻松实现这一点。
但在某些平台上,这并不容易。因此,我构建了一个只有Python的解决方案,名为build.py
"""Create runnable archives from program files and custom modules."""
import os
import py_compile
import tempfile
import zipfile as z
def mkarchive(name, modules, main='__main__.py',
shebang=b'#!/usr/bin/env python3\n'):
"""Create a runnable archive.
Arguments:
name: Name of the archive.
modules: Module name or iterable of module names to include.
main: Name of the main file. Defaults to __main__.py
shebang: Description of the interpreter to use. Defaults to Python 3.
"""
std = '__main__.py'
if isinstance(modules, str):
modules = [modules]
if main != std:
try:
os.remove(std)
except OSError:
pass
os.link(main, std)
# Forcibly compile __main__.py lest we use an old version!
py_compile.compile(std)
tmpf = tempfile.TemporaryFile()
with z.PyZipFile(tmpf, mode='w', compression=z.ZIP_DEFLATED) as zf:
zf.writepy(std)
for m in modules:
zf.writepy(m)
if main != std:
os.remove(std)
tmpf.seek(0)
archive_data = tmpf.read()
tmpf.close()
with open(name, 'wb') as archive:
archive.write(shebang)
archive.write(archive_data)
os.chmod(name, 0o755)
if __name__ == '__main__':
pass
这不应该在未经修改的情况下使用
将build.py
复制到项目中。然后根据下面给出的示例,在uuu name uuu=='uuu main uuu'
中自定义后面的零件
假设目录src
包含几个Python文件,eggs.py
,ham.py
和foo.py
。它还包含一个子目录spam
,其中包含所有脚本都使用的Python模块。以下代码将创建三个可执行归档文件,eggs
、ham
和foo
:
if __name__ == '__main__':
from shutil import copy
os.chdir('src')
programs = [f for f in os.listdir('.') if f.endswith('.py')]
for pyfile in programs:
name = pyfile[:-3]
mkarchive(name, 'spam', pyfile)
copy(name, '../'+name)
os.remove(name)
如果您只想使用单个文件:
if __name__ == '__main__':
mkarchive('scriptname', None, 'filename.py')
Unix附带Python。如果您没有依赖项,只需使.py文件可执行,添加一个hash bang并发送它。如果您不想教他们如何运行它,您可以耐心等待他们学习。@jornsharpe打包通常没有那么简单,除非您没有依赖项,并且您知道目标机器Python版本是兼容的。更好的方法是编写一个setup.py
文件并创建一个发行版。相关的,如果不是重复的话:@wim,可能需要更多的信息。我认为这两种方法都很酷,谢谢!关于这一点,有两个问题。整个脚本只是一个名为GradeCalculator.py的文件。在这种情况下,我需要在if name='main':下以mkarchive开头的行,还是可以省略该行?(看起来这行与子目录spam有关。在我的情况下,我没有任何额外的子目录)。我以前可能应该提到我的脚本的简单性。第二个问题是,我是否省略了“pass”(第一块代码中的最后一行)?哦,好的,我知道现在发生了什么。谢谢,这很有效。我不得不对你的代码进行一些编辑,因为我没有使用额外的模块,但除此之外,一切正常。