将 Python 文件打包成单个 .py 脚本

编程入门 行业动态 更新时间:2024-10-22 16:35:28
本文介绍了将 Python 文件打包成单个 .py 脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

有谁知道是否有任何工具可以将使用多个文件和模块的 Python 项目打包到一个脚本中?

Does anybody know if there is any tool for packing a Python project that uses several files and modules into a single script?

推荐答案

另存为 python_header.py:

#!/bin/env/python # -*- coding: ascii -*- import os import sys import imp import tarfile import tempfile RUN_MODULE = "__run__" SENTINEL = 'RzlBTXhya3ljIzl6PFFkQiRKLntEdHF+c2hvWid0IX5NVlxWd' \ 'FxcJ0NWQ2xKVUI0TVEuNl0rWUtnKiRr'.decode('base64') class FileOffset(object): def __init__(self, fileobj, offset=0): self._fileobj = fileobj self._offset = offset self._fileobj.seek(offset) def tell(self): return self._fileobj.tell() - self._offset def seek(self, position, whence=os.SEEK_SET): if whence == os.SEEK_SET: if position < 0: raise IOErrror("Negative seek") self._fileobj.seek(position + self._offset) else: oldposition = self._fileobj.tell() self._fileobj.seek(position, whence) if self._fileobj.tell() < self._offset: self._fileobj.seek(oldposition, os.SEEK_SET) raise IOError("Negative seek") def __getattr__(self, attrname): return getattr(self._fileobj, attrname) def __enter__(self, *args): return self._fileobj.__enter__(*args) def __exit__(self, *args): return self._fileobj.__exit__(*args) class TarImport(object): def __init__(self, tarobj, tarname=None): if tarname is None: tarname = '<tarfile>' self._tarname = tarname self._tarobj = tarobj def find_module(self, name, path=None): module_path = os.path.join(*name.split('.')) package_path = os.path.join(module_path, '__init__') for path in [module_path, package_path]: for suffix, mode, module_type in imp.get_suffixes(): if module_type != imp.PY_SOURCE: continue member = os.path.join(path) + suffix try: modulefileobj = self._tarobj.extractfile(member) except KeyError: pass else: return Loader(name, modulefileobj, "%s/%s" % (self._tarname, member), (suffix, mode, module_type)) class Loader(object): def __init__(self, name, fileobj, filename, description): self._name = name self._fileobj = fileobj self._filename = filename self._description = description def load_module(self, name): imp.acquire_lock() try: module = sys.modules.get(name) if module is None: module = imp.new_module(name) module_script = self._fileobj.read() module.__file__ = self._filename module.__path__ = [] sys.modules[name] = module exec(module_script, module.__dict__, module.__dict__) finally: imp.release_lock() return module def find_offset(fileobj, sentinel): read_bytes = 0 for line in fileobj: try: offset = line.index(sentinel) except ValueError: read_bytes += len(line) else: return read_bytes + offset + len(sentinel) raise ValueError("sentinel not found in %r" % (fileobj, )) if __name__ == "__main__": sys.argv[:] = sys.argv[1:] archive_path = os.path.abspath(sys.argv[0]) archive_offset = find_offset(open(archive_path), SENTINEL) archive = FileOffset(open(archive_path), archive_offset) tarobj = tarfile.TarFile(fileobj=archive) importer = TarImport(tarobj, archive_path) sys.meta_path.insert(0, importer) importer.find_module(RUN_MODULE).load_module(RUN_MODULE)

另存为sh_header.sh:

#!/bin/sh head -n @@TO@@ "$0" | tail -n +@@FROM@@ | python - "$0" exit $?

另存为create_tarred_program.py:

#!/usr/bin/env python # -*- coding: latin-1 -*- import sys import imp import shutil sh_filename, runner_filename, tar_archive, dst_filename = sys.argv[1:] runner = imp.load_module("tarfile_runner", open(runner_filename, 'U'), runner_filename, ('.py', 'U', imp.PY_SOURCE)) sh_lines = open(sh_filename, 'r').readlines() runner_lines = open(runner_filename, 'r').readlines() sh_block = ''.join(sh_lines) runner_block = ''.join(runner_lines) if runner.SENTINEL in runner_block or runner.SENTINEL in sh_block: raise ValueError("Can't have the sentinel inside the runner module") if not runner_block.endswith('\n') or not sh_block.endswith('\n'): raise ValueError("Trailing newline required in both headers") to_pos = len(sh_lines) + len(runner_lines) from_pos = len(sh_lines) + 1 sh_block = sh_block.replace("@@TO@@", str(to_pos)) sh_block = sh_block.replace("@@FROM@@", str(from_pos)) dst = open(dst_filename, 'wb') dst.write(sh_block) dst.write(runner_block) dst.write(runner.SENTINEL) shutil.copyfileobj(open(tar_archive, 'rb'), dst) dst.flush() dst.close()

使用名为 packages.tar 的包创建 tar 存档.主模块应该被称为__run__.py,你不应该导入__main__.运行:

Create a tar archive with your packages named packages.tar. The main module should be called __run__.py, you should never import __main__. Run:

create_tarred_program.py sh_header.sh python_header.py packages.tar program.sh

分发program.sh.

可以通过扩展的第一行来避免对 /bin/sh 的依赖,但它仍然不能用于除 *nix 之外的任何东西,因此没有意义.

It's possible to avoid dependency on /bin/sh by an extended first line, but it still won't work on anything but *nix, so there's no point in it.

更多推荐

将 Python 文件打包成单个 .py 脚本

本文发布于:2023-07-14 22:00:06,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1107274.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:脚本   文件   Python   py

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!