Estoy trabajando en un simple trozo de código que se ejecuta una función de Python de una aplicación C/C++. En orden a ello me puse el PYTHONPATH inicializar y ejecutar de la siguiente manera:

Py_SetPythonHome("../Python27");
Py_InitializeEx(0);

Entonces puedo importar mi módulo y ejecutar la función. Funciona a la perfección.

Ahora estoy intentando crear un instalador para mis colegas para que se ejecute el código. Quiero minimizar el número de archivos que necesito incluir en este programa de instalación, por razones obvias.

El google el tema me dice que yo debería ser capaz de incluir los archivos «Python27.lib» y «Python27.dll», a continuación, cierre la cremallera de la «Dll» y «Lib» de las carpetas y los incluyen. Sin embargo, cuando intento esto, Py_Initialize falla.

Un rápido examen de cuál es la causa de este error se muestra que Py_Initialize parece depender de un número de .pyc archivos en la carpeta Lib, incluyendo (pero no limitado a advertencias.pyc, _abcoll.pyc, _future_.pyc y el contenido de la «codificación» de la carpeta.

No puedo entender por qué. Algún consejo?

InformationsquelleAutor Matt McC | 2016-09-16

1 Comentario

  1. 3

    Al principio, yo quería decir que no hay ningún módulo obligatorio (al menos no no builtin uno) para Py_InitializeEx, por lo que el único requisito era python27.dll (por cierto: python27.lib es no requerido, a menos que sus colegas desea vincular a algo en contra de ella – pero que no sería muy fácil w/o Python‘s Incluyen dir.). Yo tenía este código (BTW: estoy usando Python 2.7.10 que he construido utilizando VStudio 10 (2010)):

    #include <stdio.h>
    #include <conio.h>
    #include <Python.h>
    
    int main() {
        int i = 0;
        char *pyCode = 
            "s = \"abc\"\n"
            "print s, 1234";
        Py_InitializeEx(0);
        i = PyRun_SimpleString(pyCode);
        Py_Finalize();
        printf("PyRun_SimpleString returned: %d\nPress a key to exit...\n", i);
        _getch();
        return 0;
    }

    Se construyó muy bien, que se corrió ACEPTAR de VStudio, y desde la línea de comandos (después de copiar el .dll en su carpeta). Pero luego he copiado el .exe y .dll a otro equipo y cuando se ejecuta, bang!!!

    ImportError: No module named site

    Considerando que:

    • No tengo PYTHON* env variables establece en ninguna de las consolas en las 2 máquinas donde me encontré con la .exe (con diferentes resultados)
    • En ambos equipos el Python instalación está en el mismo camino (yo antes (hace años) modificado en la máquina que no funciona)

    No sé por qué no se comportan de la misma (una cosa que no he comprobar es que puede haber alguna clave de registro en la máquina que funciona?).

    Nota: sitio es un (.py(c)) módulo situado bajo %PYTHON_INSTALL_DIR%\Lib.

    Entonces, busqué Python‘s código fuente y me encontré con esto (archivo: pythonrun.c, línea: 269, la función Py_InitializeEx o pythonrun.c:269: Py_InitializeEx – esta es la forma en que me voy a referir a un punto en el código fuente):

        if (!Py_NoSiteFlag)
            initsite(); /* Module site */

    mientras que en pythonrun.c:727: initsite:

        m = PyImport_ImportModule("site");

    que es bastante obvio (Py_NoSiteFlag es 0).

    Entonces me di cuenta de que Py_NoSiteFlag se declara como extern __declspec(dllexport) ([La SEÑORA Docs]: Uso externo para Especificar la Vinculación, [La SEÑORA Docs]: dllexport, dllimport), así que he modificado el código para:

    #include <stdio.h>
    #include <conio.h>
    #include <Python.h>
    
    extern __declspec(dllimport) int Py_NoSiteFlag;
    
    int main() {
        int i = 0;
        char *pyCode = 
            "s = \"abc\"\n"
            "print s, 1234";
        Py_NoSiteFlag = 1;
        Py_InitializeEx(0);
        i = PyRun_SimpleString(pyCode);
        Py_Finalize();
        printf("PyRun_SimpleString returned: %d\nPress a key to exit...\n", i);
        _getch();
        return 0;
    }

    y funciona! Yay!

    Así, en este punto, sólo el .dll es necesario para ejecutar un trozo de código. Pero me imagino que el código es «un poco» más compleja que la que (tiene de importacións ([Python 2.Docs]: La declaración de importación). Para resolver el de importación problema, puede utilizar este bonito módulo: [Python 2.Docs]: modulefinder – Encontrar módulos utilizados por una secuencia de comandos (parte de Python 2.7‘s módulos estándar). Para hacer uso de ella:

    • Guardar el código que se ejecuta desde C en un .py archivo
    • Ejecutar modulefinder contra

    He aquí un ejemplo de mi código (pyCode contenido en mi C programa, se guardan en un archivo).

    code.py:

    s = "abc"
    print s, 1234

    Ejecución:

    %PYTHON_INSTALL_DIR%\python -m modulefinder code.py

    rendimientos:

    Name                      File
    ----                      ----
    m __main__                code.py

    Pero, si puedo añadir un import os (que es una situación muy común módulo) declaración en el archivo, el comando anterior se obtiene:

    Name                        File
    ----                        ----
    m StringIO                  %PYTHON_INSTALL_DIR%\lib\StringIO.py
    m UserDict                  %PYTHON_INSTALL_DIR%\lib\UserDict.py
    m __builtin__
    m __future__                %PYTHON_INSTALL_DIR%\lib\__future__.py
    m __main__                  a.py
    m _abcoll                   %PYTHON_INSTALL_DIR%\lib\_abcoll.py
    m _codecs
    m _collections
    m _functools
    m _hashlib                  %PYTHON_INSTALL_DIR%\DLLs\_hashlib.pyd
    m _heapq
    m _io
    m _locale
    m _random
    m _sre
    m _struct
    m _subprocess
    m _threading_local          %PYTHON_INSTALL_DIR%\lib\_threading_local.py
    m _warnings
    m _weakref
    m _weakrefset               %PYTHON_INSTALL_DIR%\lib\_weakrefset.py
    m abc                       %PYTHON_INSTALL_DIR%\lib\abc.py
    m array
    m atexit                    %PYTHON_INSTALL_DIR%\lib\atexit.py
    m bdb                       %PYTHON_INSTALL_DIR%\lib\bdb.py
    m binascii
    m cPickle
    m cStringIO
    m cmd                       %PYTHON_INSTALL_DIR%\lib\cmd.py
    m codecs                    %PYTHON_INSTALL_DIR%\lib\codecs.py
    m collections               %PYTHON_INSTALL_DIR%\lib\collections.py
    m copy                      %PYTHON_INSTALL_DIR%\lib\copy.py
    m copy_reg                  %PYTHON_INSTALL_DIR%\lib\copy_reg.py
    m difflib                   %PYTHON_INSTALL_DIR%\lib\difflib.py
    m dis                       %PYTHON_INSTALL_DIR%\lib\dis.py
    m doctest                   %PYTHON_INSTALL_DIR%\lib\doctest.py
    m dummy_thread              %PYTHON_INSTALL_DIR%\lib\dummy_thread.py
    P encodings                 %PYTHON_INSTALL_DIR%\lib\encodings\__init__.py
    m encodings.aliases         %PYTHON_INSTALL_DIR%\lib\encodings\aliases.py
    m errno
    m exceptions
    m fnmatch                   %PYTHON_INSTALL_DIR%\lib\fnmatch.py
    m functools                 %PYTHON_INSTALL_DIR%\lib\functools.py
    m gc
    m genericpath               %PYTHON_INSTALL_DIR%\lib\genericpath.py
    m getopt                    %PYTHON_INSTALL_DIR%\lib\getopt.py
    m gettext                   %PYTHON_INSTALL_DIR%\lib\gettext.py
    m hashlib                   %PYTHON_INSTALL_DIR%\lib\hashlib.py
    m heapq                     %PYTHON_INSTALL_DIR%\lib\heapq.py
    m imp
    m inspect                   %PYTHON_INSTALL_DIR%\lib\inspect.py
    m io                        %PYTHON_INSTALL_DIR%\lib\io.py
    m itertools
    m keyword                   %PYTHON_INSTALL_DIR%\lib\keyword.py
    m linecache                 %PYTHON_INSTALL_DIR%\lib\linecache.py
    m locale                    %PYTHON_INSTALL_DIR%\lib\locale.py
    P logging                   %PYTHON_INSTALL_DIR%\lib\logging\__init__.py
    m marshal
    m math
    m msvcrt
    m nt
    m ntpath                    %PYTHON_INSTALL_DIR%\lib\ntpath.py
    m opcode                    %PYTHON_INSTALL_DIR%\lib\opcode.py
    m operator
    m optparse                  %PYTHON_INSTALL_DIR%\lib\optparse.py
    m os                        %PYTHON_INSTALL_DIR%\lib\os.py
    m os2emxpath                %PYTHON_INSTALL_DIR%\lib\os2emxpath.py
    m pdb                       %PYTHON_INSTALL_DIR%\lib\pdb.py
    m pickle                    %PYTHON_INSTALL_DIR%\lib\pickle.py
    m posixpath                 %PYTHON_INSTALL_DIR%\lib\posixpath.py
    m pprint                    %PYTHON_INSTALL_DIR%\lib\pprint.py
    m random                    %PYTHON_INSTALL_DIR%\lib\random.py
    m re                        %PYTHON_INSTALL_DIR%\lib\re.py
    m repr                      %PYTHON_INSTALL_DIR%\lib\repr.py
    m select                    %PYTHON_INSTALL_DIR%\DLLs\select.pyd
    m shlex                     %PYTHON_INSTALL_DIR%\lib\shlex.py
    m signal
    m sre_compile               %PYTHON_INSTALL_DIR%\lib\sre_compile.py
    m sre_constants             %PYTHON_INSTALL_DIR%\lib\sre_constants.py
    m sre_parse                 %PYTHON_INSTALL_DIR%\lib\sre_parse.py
    m stat                      %PYTHON_INSTALL_DIR%\lib\stat.py
    m string                    %PYTHON_INSTALL_DIR%\lib\string.py
    m strop
    m struct                    %PYTHON_INSTALL_DIR%\lib\struct.py
    m subprocess                %PYTHON_INSTALL_DIR%\lib\subprocess.py
    m sys
    m tempfile                  %PYTHON_INSTALL_DIR%\lib\tempfile.py
    m textwrap                  %PYTHON_INSTALL_DIR%\lib\textwrap.py
    m thread
    m threading                 %PYTHON_INSTALL_DIR%\lib\threading.py
    m time
    m token                     %PYTHON_INSTALL_DIR%\lib\token.py
    m tokenize                  %PYTHON_INSTALL_DIR%\lib\tokenize.py
    m traceback                 %PYTHON_INSTALL_DIR%\lib\traceback.py
    m types                     %PYTHON_INSTALL_DIR%\lib\types.py
    P unittest                  %PYTHON_INSTALL_DIR%\lib\unittest\__init__.py
    m unittest.case             %PYTHON_INSTALL_DIR%\lib\unittest\case.py
    m unittest.loader           %PYTHON_INSTALL_DIR%\lib\unittest\loader.py
    m unittest.main             %PYTHON_INSTALL_DIR%\lib\unittest\main.py
    m unittest.result           %PYTHON_INSTALL_DIR%\lib\unittest\result.py
    m unittest.runner           %PYTHON_INSTALL_DIR%\lib\unittest\runner.py
    m unittest.signals          %PYTHON_INSTALL_DIR%\lib\unittest\signals.py
    m unittest.suite            %PYTHON_INSTALL_DIR%\lib\unittest\suite.py
    m unittest.util             %PYTHON_INSTALL_DIR%\lib\unittest\util.py
    m warnings                  %PYTHON_INSTALL_DIR%\lib\warnings.py
    m weakref                   %PYTHON_INSTALL_DIR%\lib\weakref.py
    Missing modules:
    ? _emx_link imported from os
    ? ce imported from os
    ? fcntl imported from subprocess, tempfile
    ? org.python.core imported from copy, pickle
    ? os.path imported from os, shlex
    ? os2 imported from os
    ? posix imported from os
    ? pwd imported from posixpath
    ? readline imported from cmd, pdb
    ? riscos imported from os
    ? riscosenviron imported from os
    ? riscospath imported from os

    Como se puede ver, hay una muy gran cantidad de módulos (he modificado la salida un poco, en lugar de la ruta real que me colocaron el %PYTHON_INSTALL_DIR% env var). En orden para el Python código de trabajo, usted tendrá que incluir todos los módulos/paquetes en el instalador.

    Notas sobre modulefinder‘s de salida (que me he dado cuenta mientras que jugaba con él):

    De este modo, en los módulos que son requeridos por os, no estoy seguro de que la toma de la sitio importación de C hace mucha diferencia.

    NOTA IMPORTANTE: Para asegurarse de que su .exe funciona en cualquier equipo, usted podría considerar la inclusión de VStudio C Runtime Library o VCRTLib (msvcr##(#).dll: [La SEÑORA Docs]: Biblioteca de Tiempo de Ejecución de Referencia) (donde #s son marcadores de posición de dígitos que representan VStudio versión) en su instalador.

    • Gracias! Esto es exactamente lo que yo necesitaba. Ajuste de la Py_NoSiteFlag a 1 se ha solucionado el problema, y la importación de módulos adicionales es sencillo! Gracias por tu ayuda.

Dejar respuesta

Please enter your comment!
Please enter your name here