2009-09-07 13 views
16

Estoy desarrollando en Windows, y he buscado en todas partes sin encontrar a nadie hablando de este tipo de cosas.C++ con incrustación de Python: bloqueo si Python no está instalado

Hice una aplicación C++ en mi escritorio que incrustó Python 3.1 usando MSVC. Conecté python31.lib e incluí python31.dll en la carpeta de ejecución de la aplicación junto al ejecutable. Funciona muy bien. Mi código de extensión e incrustación definitivamente funciona y no hay fallas.

Envié la carpeta de ejecución a mi amigo que no tiene Python instalado, y la aplicación falla para él durante la fase de configuración de scripting.

Hace unas horas, probé la aplicación en mi computadora portátil que tiene Python 2.6 instalado. Obtuve el mismo comportamiento de bloqueo que mi amigo, y mediante la depuración descubrí que era la llamada Py_Initialize() la que falla.

Instalé Python 3.1 en mi computadora portátil sin cambiar el código de la aplicación. Lo ejecuté y funciona perfectamente. Desinstalé Python 3.1 y la aplicación se bloquea de nuevo. Puse el código en mi aplicación para vincular dinámicamente desde el python31.dll local, para asegurarme de que lo estaba usando, pero sigo teniendo el bloqueo.

No sé si el intérprete necesita más que la DLL para iniciar o qué. No he podido encontrar ningún recurso sobre esto. La documentación de Python y otras guías parecen no tener en cuenta cómo distribuir sus aplicaciones C/C++ que usan la incrustación de Python sin que los usuarios instalen Python localmente. Sé que es más un problema en Windows que en Unix, pero he visto varias aplicaciones de Windows C/C++ que incrustan Python localmente y no estoy seguro de cómo lo hacen.

¿Qué más necesito aparte de la DLL? ¿Por qué funciona cuando instalo Python y luego dejo de funcionar cuando lo desinstalo? Parece que debería ser tan trivial; tal vez es por eso que nadie realmente habla de eso. Sin embargo, realmente no puedo explicar cómo lidiar con este problema.

Muchas gracias de antemano.

+1

¿Su llamada a loadlibrary tiene éxito? ¿Dónde estás poniendo el dll? Podría ser tan simple como que la aplicación no pueda encontrar la biblioteca. – patros

+1

LoadLibrary tuvo éxito, al igual que GetProcAddress. Como recibí la misma excepción que hice sin el enlace dinámico (en lugar de una violación de acceso NULL), creo que se llamó a Py_Initialize. La DLL está en el directorio de ejecución. Mi directorio de ejecución contiene:. \ Ss_server.exe,. \ Python31.dll,. \ Admin.sqlite,. \ Settings.py,. \ Err.txt – apostrophest

Respuesta

20

Además de pythonxy.dll, también necesita toda la biblioteca de Python, es decir, el contenido de la carpeta lib, más los módulos de extensión, es decir, el contenido de la carpeta DLL. Sin la biblioteca estándar, Python ni siquiera se iniciará, ya que trata de encontrar os.py (en 3.x; string.py en 2.x). Al inicio, importa varios módulos, en particular site.py.

Hay varios lugares donde busca la biblioteca estándar; en sus casos, eventualmente lo encuentra en el registro. Antes, usa el nombre del ejecutable (como se establece a través de Py_SetProgramName) tratando de encontrar el hito; también comprueba si hay un archivo python31.zip que debe ser una copia comprimida de la biblioteca estándar. También busca una variable de entorno PYTHONHOME.

Usted es libre de quitar la biblioteca de cosas que no necesita; hay varias herramientas que calculan las dependencias de forma estática (en particular, el buscador de módulos).

Si desea reducir al mínimo el número de archivos, puede

  1. enlace de todos los módulos de extensión de forma estática en su pythonxy.dll, o incluso enlace pythonxy.dll estáticamente en su aplicación
  2. utilizar la herramienta de congelación ; esto permitirá vincular el código de bytes de la biblioteca estándar en su pythonxy.dll.
  3. (alternativamente a 2.) use pythonxy.zip para la biblioteca estándar.
+0

Gracias, Martin. Su explicación llena algunos de los vacíos que no pude llenar mientras buscaba una respuesta. Investigaré algunas de las soluciones propuestas. – apostrophest

+1

Hice un python31.zip que consta de C: \ Python31 \ Lib \ *. * Y C: \ Python31 \ DLLs \ *. * Puse esto junto con mi aplicación EXE y python31.dll. ¡El programa funciona! El zip es de 13 megas, así que, como sugieres, debería averiguar qué es lo que necesito y reducirlo. Estoy marcando esto como una solución, ¡muchas gracias! – apostrophest

+0

No pude hacer que python26.zip funcionara, intenté casi todo. ¿Estás seguro de que python * no * se instaló cuando python31.zip funcionó? ¡Todas las demás publicaciones en stackoverflow (haciendo que pythonxx.zip funcione) también quedan sin respuesta! – sambha

11

Agradable. Y si no quiere comprimir, copiar Python26 \ DLL & Python26 \ lib en el directorio exe como:

.\myexe.exe  
.\python26.dll 
.\Python26\DLLs 
.\Python26\lib 

y después fijar los PYTHONHOME con Py_SetPythonHome (API). Aparentemente, esta API no está en la lista de llamadas "permitidas" antes de Py_Initialize();

A continuación trabajó para mí en Windows (Python no instalado):

#include "stdafx.h" 
#include <iostream> 
#include "Python.h" 

using namespace std; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    char pySearchPath[] = "Python26"; 
    Py_SetPythonHome(pySearchPath); 
    Py_Initialize(); 
    PyRun_SimpleString("from time import time,ctime\n" 
        "print 'Today is',ctime(time())\n"); 
    //cerr << Py_GetPath() << endl; 
    Py_Finalize(); 

    return 0; 
} 

buena que la ruta de búsqueda es relativo w.r.t el exe. Py_GetPath puede mostrarle dónde está buscando los módulos.

+0

la solución anterior funcionó bien para el usuario administrador. para usuarios no administradores, sin embargo, la aplicación no se inicia. algunas ideas ? –

+0

@balasbellobas ¿Tienes pywin32 en tu pitón? Creo que tuve un problema similar (las llamadas integradas de Excel funcionaban solo como "administrador"). Hubo un problema gen_py donde python intentó crear archivos en una carpeta no permitida (quizás archivos de programa). Es posible que desee buscar más en gen_py. Creo que solo tuve que eliminar algunos archivos. Espero eso ayude. – sambha

5

Un zip de la biblioteca estándar de Python funcionó para mí con Python27.

Comprimí el contenido de Lib y dll, y me aseguré de que no hubiera ninguna subcarpeta python27 o subcarpeta Lib o dll. es decir, solo un zip llamado python27.zip que contiene todos los archivos.

Copié ese zip y python27.dll junto con el ejecutable.

6

Quería agregar algo de información adicional para otros que todavía podrían tener problemas con esto, como yo. Yo era finalmente capaz de conseguir mi solicitud de trabajo utilizando el método propuesto por Sambha usuario, que es:

 
Program Files (x86)\ 
    MyApplicationFolder\ 
     MyApplication.exe 
     python27.dll 
     Python27\ 
      DLLs\ (contents of DLLs folder) 
      Lib\ (contents of Lib folder) 

... con una adición importante: También necesitaba para instalar el Msvcr90.dll. Estoy usando Python 2.7 y aparentemente python27.dll requiere MSVCR90.DLL (y tal vez otros MSVC * 90.DLL).

Lo resolví descargando, instalando y ejecutando el paquete 'vcredist_x86.exe' de http://www.microsoft.com/en-us/download/details.aspx?id=29. Creo que, aunque no estoy seguro, debes hacerlo de esta manera, al menos en Win7, en lugar de simplemente colocar los MSVC * 90.DLL junto con tu .exe como lo hiciste en el pasado. El instalador de Microsoft coloca los archivos y los registra de manera especial bajo Win7.

También probé el método de archivo .zip pero eso no funcionó, incluso con el MSVCR90.DLL instalado.

Cuestiones relacionadas