¿Cómo concatenar múltiples archivos fuente de Python en un solo archivo?

(Suponga que: el tiempo de inicio de la aplicación es absolutamente crítico; mi aplicación se inicia mucho; mi aplicación se ejecuta en un entorno en el que la importación es más lenta de lo normal; es necesario importar muchos archivos; no está disponible la comstackción en archivos .pyc .)

Me gustaría concatenar todos los archivos de origen de Python que definen una colección de módulos en un único archivo de origen de Python.

Me gustaría que el resultado de importar el nuevo archivo sea como si hubiera importado uno de los archivos originales (que luego importaría algunos más de los archivos originales, y así sucesivamente).

es posible?

Aquí hay una simulación aproximada y manual de lo que una herramienta podría producir cuando se alimentan los archivos fuente para los módulos ‘bar’ y ‘baz’. Debería ejecutar dicha herramienta antes de implementar el código.

 __file__ = 'foo.py' def _module(_name): import types mod = types.ModuleType(name) mod.__file__ = __file__ sys.modules[module_name] = mod return mod def _bar_module(): def hello(): print 'Hello World! BAR' mod = create_module('foo.bar') mod.hello = hello return mod bar = _bar_module() del _bar_module def _baz_module(): def hello(): print 'Hello World! BAZ' mod = create_module('foo.bar.baz') mod.hello = hello return mod baz = _baz_module() del _baz_module 

Y ahora puedes:

 from foo.bar import hello hello() 

Este código no tiene en cuenta cosas como las declaraciones de importación y las dependencias. ¿Hay algún código existente que ensamblará los archivos de origen utilizando esta u otra técnica?

Esta es una idea muy similar a las herramientas que se utilizan para ensamblar y optimizar archivos JavaScript antes de enviarlos al navegador, donde la latencia de múltiples solicitudes HTTP afecta el rendimiento. En este caso de Python, lo que duele es la latencia de importar cientos de archivos de origen de Python en el inicio.

Si esto está en el motor de Google Apps, como indican las tags, asegúrese de estar usando este idioma.

 def main(): #do stuff if __name__ == '__main__': main() 

Debido a que GAE no reinicia su aplicación en cada solicitud a menos que el .py haya cambiado, simplemente ejecuta main() nuevamente.

Este truco te permite escribir aplicaciones de estilo CGI sin el golpe de rendimiento de inicio

AppCaching

Si un script de controlador proporciona una rutina main (), el entorno de ejecución también almacena en caché el script. De lo contrario, el script del controlador se carga para cada solicitud.

Creo que debido a la precomstackción de archivos Python y algunos caché del sistema, la velocidad que eventualmente obtendrá no será medible.

Hacer esto es poco probable que produzca beneficios de rendimiento. Aún estás importando la misma cantidad de código Python, solo en menos módulos, y estás sacrificando toda la modularidad por ello.

Un mejor enfoque sería modificar su código y / o bibliotecas para que solo importen cosas cuando sea necesario, de modo que se cargue un mínimo de código requerido para cada solicitud.

Sin abordar la pregunta, si esta técnica impulsaría o no las cosas en su entorno, diga que tiene razón, esto es lo que habría hecho.

Haría una lista de todos mis módulos, por ejemplo, my_files = ['foo', 'bar', 'baz']

Luego usaría las utilidades os.path para leer todas las líneas en todos los archivos del directorio de origen y las escribiré en un nuevo archivo, filtrando todas las líneas import foo|bar|baz ya que todo el código está ahora dentro de un solo archivo.

Por supuesto, al final, agregando main() de __init__.py (si existe) al __init__.py del archivo.