¿Alguien sabe si hay alguna herramienta para empaquetar un proyecto de Python que use varios archivos y módulos en un solo script?Embalaje de archivos de Python en un solo script .py
Respuesta
Guardar esto como 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)
Guardar esto como sh_header.sh
:
#!/bin/sh
head -n @@[email protected]@ "$0" | tail -n [email protected]@[email protected]@ | python - "$0"
exit $?
Guardar esto como 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("@@[email protected]@", str(to_pos))
sh_block = sh_block.replace("@@[email protected]@", 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()
Crear un tar una rchive con sus paquetes llamados packages.tar
. El módulo principal se debe llamar __run__.py
, nunca debe importar __main__
. Ejecutar:
create_tarred_program.py sh_header.sh python_header.py packages.tar program.sh
distrubute program.sh
.
Es posible evitar la dependencia de /bin/sh
por una primera línea extendida, pero aún así no funcionará en nada excepto * nix, por lo que no tiene sentido.
Parece que ha hecho un gran trabajo aquí. ¿Este código está disponible en otro lugar, como PyPI? –
hacer el archivo .egg e instalarlo o ponerlo en pythonpath puede resolver su problema.
similar fellow
me acaba de hacer esto: https://github.com/fgarcia/snips/tree/master/pydeploy
El enlace está roto. –
- 1. Compilación de archivos .py en .pyo sin recurrir a un script de contenedor
- 2. Llamar código python (archivos .py) desde C#
- 3. Embalaje de múltiples .exe en un solo paquete .msi
- 4. Importación de archivos en Python desde __init__.py
- 5. API de un paquete en python. En __init__.py?
- 6. Python: ¿cómo se ejecuta un archivo .py?
- 7. Embalaje de archivos Javascript en una guerra?
- 8. Configuración setup.py para el embalaje de un solo archivo .py y un único archivo de datos sin necesidad de crear ninguna carpeta
- 9. Codificación para archivos .py multilingües
- 10. Registro de Python solo registro del script
- 11. ¿Permitir solo una instancia de script python?
- 12. Ejecutar un script de python desde otro script de python, pasando args
- 13. Script de python "Bootstrap" en el shell de Windows sin asociaciones .py/.pyw
- 14. Inicie python .py como un servicio en Windows
- 15. Embalaje máximo de rectángulos en un círculo
- 16. A veces PyDev no reconoce archivos .py como archivos fuente de Python
- 17. Terminar un script de python desde otro script de python
- 18. embalaje Node.js-Scripts + NODE.EXE en un único ejecutable
- 19. No se pueden ejecutar los archivos Python .py desde la terminal en Mac
- 20. ¿Cómo crear una función de embalaje optimizada en python?
- 21. ¿Expandir pestañas a espacios en vim solo en archivos Python?
- 22. ¿Cómo dividir la aplicación del matraz en varios archivos py?
- 23. ¿Cómo modificar un buffer Vim con un script python?
- 24. ¿Cómo se puede cambiar la asociación de archivos para .py Python en XP?
- 25. archivos PyInstaller pero manteniendo .py actualizables
- 26. Importación de módulos en Python y __init__.py
- 27. salida del script en Python desde dentro de un script en Python
- 28. Llamar a un script de Python desde un Applescript
- 29. Importar un módulo python sin la extensión .py
- 30. Ejecutar 4 instancias concurrentes de un script de python en una carpeta de archivos de datos
¿Cuál es el propósito de embalaje en un único script .py como se indica en el título? Si necesita combinar (python en sí mismo + módulos de terceros + código) para fines de instalación u otro: consulte 'pyinstaller' ... – ChristopheD
Necesito poder copiar solo un archivo y luego importarlo o ejecutarlo. A veces es mucho más conveniente copiar un único archivo en lugar de copiar todo el árbol del proyecto. –
Posiblemente sea posible (si, por ejemplo, abusó de las clases como espacios de nombres y si su código no es demasiado ingenioso/hacky con respecto al alcance/espacios de nombres/importación interna), pero ciertamente nocivo para el desarrollo y no necesario para la implementación. Así que espero que nadie se moleste en hacer tal herramienta. – delnan