¿Cómo implementar una aplicación Python con bibliotecas como fuente sin más dependencias?

Antecedentes : tengo una pequeña aplicación Python que hace que la vida de los desarrolladores que lanzan software en nuestra empresa sea un poco más fácil. Construyo un ejecutable para Windows usando py2exe. La aplicación, así como el binario, están registrados en Subversion. La distribución es realizada por personas que solo revisan el directorio de SVN El progtwig tiene aproximadamente 6 dependencias diferentes de la biblioteca de Python (por ejemplo, ElementTree, Mako)

La situación : los desarrolladores quieren piratear la fuente de esta herramienta y luego ejecutarla sin tener que construir el binario. Actualmente, esto significa que necesitan un intérprete de Python 2.6 (lo cual está bien) y también tienen las 6 bibliotecas instaladas localmente usando easy_install.

El problema

  • Este no es un entorno público de código abierto clásico: estoy dentro de una red corporativa, la herramienta nunca abandonará el “jardín amurallado” y tenemos barreras muy inconvenientes para acceder a Internet externo (NTLM autenticando proxies y / o máquinas sin acceso directo a internet).
  • Quiero que los obstáculos para comenzar a piratear esta herramienta sean mínimos: nadie debería tener que buscar la dependencia correcta en la versión correcta, debería tener que ejecutar la menor configuración posible. De manera óptima, los requisitos previos serían tener una instalación de Python y simplemente revisar el progtwig desde Subversion.

Anécdota : Cuanto más autocontenido es el proceso, más fácil es repetirlo. Cambié mi máquina por una nueva y pasé por el desagradable proceso de tener que aplicar ingeniería inversa a las dependencias, reinstalar los dispositivos, buscar en las bibliotecas en línea y hacer que se instalen (consulte las restricciones de Internet corporativo más arriba).

    A veces utilizo el enfoque que describo a continuación, por la misma razón que dice @Boris: Preferiría que el uso de algún código sea tan fácil como a) svn checkout / update – b) go.

    Pero para el registro:

    • Uso virtualenv / easy_install la mayor parte del tiempo.
    • Estoy de acuerdo en cierta medida con los críticos de @Ali A y @ S.Lott

    De todos modos, el enfoque que utilizo depende de la modificación de sys.path, y funciona así:

    • Requiere Python y setuptools (para habilitar la carga de códigos desde los huevos) en todas las computadoras que usarán tu software.
    • Organice su estructura de directorios esto:
     proyecto/
         * .py
         scriptcustomize.py
         archivo.pth
    
         tercero/
             huevos/
                 mako-vNNN.egg
                 ... .huevo
             código/
                 árbol de elementos
                     * .py
                 ...
    
    • En sus scripts de nivel superior, incluya el siguiente código en la parte superior:
     de script Personalizar importar apply_pth_files
     apply_pth_files (__ archivo__)
    
    • Agregue scriptcustomize.py a su carpeta de proyecto:
     importación OS
     desde glob import glob
     importar entrada de archivo
     sistemas de importación
    
     def apply_pth_files (scriptfilename, at_beginning = False):
         "" "En la parte superior de tu script:
         de script Personalizar importar apply_pth_files
         apply_pth_files (__ archivo__)
    
         ""
         directory = os.path.dirname (nombre de archivo de script)
         files = glob (os.path.join (directorio, '* .pth'))
         si no archivos:
             regreso
         para la línea en fileinput.input (archivos):
             line = line.strip ()
             si la línea y la línea [0]! = '#':
                 ruta = os.path.join (directorio, línea)
                 si se inicia
                     sys.path.insert (0, ruta)
                 más:
                     sys.path.append (ruta)
    
    • Agregue uno o más archivos * .pth a su carpeta de proyectos. En cada línea, ponga una referencia a un directorio con paquetes. Por ejemplo:
     # contenidos del archivo * .pth
     tercero / código
     Thirdparty / eggs / mako-vNNN.egg
    
    • Me gusta este tipo de enfoque. Lo que me gusta: es similar a cómo funcionan los archivos * .pth, pero para progtwigs individuales en lugar de los paquetes de todo el sitio. Lo que no me gusta: tener que agregar las dos líneas al principio de los scripts de nivel superior.
    • Una vez más: uso virtualenv la mayor parte del tiempo. Pero tiendo a usar virtualenv para proyectos donde tengo un control estricto del escenario de implementación. En los casos en los que no tengo un control estricto, tiendo a utilizar el enfoque que describí anteriormente. Hace que sea realmente fácil empaquetar un proyecto como un zip y hacer que el usuario final lo “instale” (descomprimiéndolo).

    Solo use virtualenv , es una herramienta para crear entornos Python aislados. Puede crear una secuencia de comandos de configuración y distribuir todo el grupo si lo desea.

    “No me gusta el hecho de que los desarrolladores (o yo que empecemos en una máquina nueva y limpia) tengan que saltar a través de los distantes problemas de tener que instalar las bibliotecas localmente antes de que puedan comenzar”

    ¿Por qué?

    ¿Qué – específicamente – está mal con esto?

    Lo hiciste para crear el proyecto. Tu proyecto es tan popular que otros quieren hacer lo mismo.

    No veo un problema. Por favor actualice su pregunta con los problemas específicos que necesita resolver. No le gusta la forma en que se distribuye el código abierto, no es un problema, es la forma en que funciona el código abierto.

    Editar El “jardín amurallado” no importa mucho.

    Opción 1. Podría, por cierto, construir un “instalador” que ejecute easy_install 6 veces para ellos.

    Opción 2. Puede guardar todos los kits de instalación que habría utilizado easy_install. Luego, puede proporcionar un script que python setup.py install una descompresión y una instalación de python setup.py install para los seis.

    Opción 3. Puede proporcionar una versión comprimida de sus site-packages . Después de instalar Python, descomprimen su directorio de paquetes de sitio en `C: \ Python2.5 \ lib \ site-packages“.

    Opción 4. Puede crear su propio kit de instalación de MSI para su entorno Python.

    Opción 5. Puede alojar su propio servidor tipo pypi y proporcionar una instalación fácil que primero verifique su servidor.

    Estoy de acuerdo con las respuestas de Nosklo y S.Lott. (+1 a ambos)

    ¿Puedo agregar que lo que quieres hacer es en realidad una idea terrible ?

    Si realmente quiere que la gente piratee su código, necesitarán cierta comprensión de las bibliotecas involucradas, cómo funcionan, qué son, de dónde vienen, la documentación de cada una, etc. Seguro que les proporciona un script bootstrap, pero más allá que estarás mimado hasta el punto de que no tienen ni idea.

    Luego hay problemas específicos como “¿qué sucede si un usuario desea instalar una versión o implementación diferente de una biblioteca?”, Un ejemplo evidente aquí es ElementTree, ya que tiene varias implementaciones.

    No estoy sugiriendo que esto sea una gran idea, pero generalmente lo que hago en situaciones como estas es que tengo un Makefile, registrado en Subversion, que contiene reglas de creación para recuperar todas las bibliotecas dependientes e instalarlas. El archivo MAKE puede ser lo suficientemente inteligente como para aplicar solo las bibliotecas dependientes si no están presentes, por lo que esto puede ser relativamente rápido.

    Un nuevo desarrollador en el proyecto simplemente se retira de Subversion y luego escribe “make”.

    Este enfoque podría funcionar bien para usted, dado que su audiencia ya está acostumbrada a la idea de utilizar los controles de subversión como parte de su proceso de búsqueda. Además, tiene la buena propiedad de que todos los conocimientos sobre su progtwig, incluidas sus dependencias externas, se capturan en el repository de código fuente.