Exemplo n.º 1
0
/*
 * Start python - return 0 on success
 */
int pyi_pylib_start_python(ARCHIVE_STATUS *status)
{
    /* Set sys.path, sys.prefix, and sys.executable so dynamic libs will load.
     *
     * The Python APIs we use here (Py_SetProgramName, Py_SetPythonHome)
     * specify their argument should be a "string in static storage".
     * That is, the APIs use the string pointer as given and will neither copy
     * its contents nor free its memory.
     *
     * NOTE: Statics are zero-initialized. */
	static char pypath[2*PATH_MAX + 14];
	static char pypath_sfn[2*PATH_MAX +14];
	static char pyhome[PATH_MAX+1];
	static char progname[PATH_MAX+1];

    /* Wide string forms of the above, for Python 3. */
	static wchar_t pypath_w[PATH_MAX+1];
	static wchar_t pyhome_w[PATH_MAX+1];
	static wchar_t progname_w[PATH_MAX+1];

    if (is_py2) {
#ifdef _WIN32
		/* Use ShortFileName - affects sys.executable */
		if(!pyi_win32_utf8_to_mbs_sfn(progname, status->archivename, PATH_MAX)) {
			FATALERROR("Failed to convert progname to wchar_t\n");
			return -1;
		}
#else
		/* Use system-provided filename. No encoding. */
		strncpy(progname, status->archivename, PATH_MAX);
#endif
      	PI_Py2_SetProgramName(progname);
    } else {
		/* Decode using current locale */
		if(!pyi_locale_char2wchar(progname_w, status->archivename, PATH_MAX)) {
			FATALERROR("Failed to convert progname to wchar_t\n");
			return -1;
		}
        // In Python 3 Py_SetProgramName() should be called before Py_SetPath().
        PI_Py_SetProgramName(progname_w);
    };

    /* Set sys.path */
    VS("LOADER: Manipulating environment (sys.path, sys.prefix)\n");
    if(is_py2) {
    	/* sys.path = [mainpath] */
    	strncpy(pypath, status->mainpath, strlen(status->mainpath));
    } else {
    	/* sys.path = [base_library, mainpath] */
        strncpy(pypath, status->mainpath, strlen(status->mainpath));
		strncat(pypath, PYI_SEPSTR, strlen(PYI_SEPSTR));
		strncat(pypath, "base_library.zip", strlen("base_library.zip"));
		strncat(pypath, PYI_PATHSEPSTR, strlen(PYI_PATHSEPSTR));
		strncat(pypath, status->mainpath, strlen(status->mainpath));
    };
    /*
     * On Python 3, we must set sys.path to have base_library.zip before
     * calling Py_Initialize as it needs `encodings` and other modules.
     */
    if (!is_py2) {
        /* Decode using current locale */
		if(!pyi_locale_char2wchar(pypath_w, pypath, PATH_MAX)) {
			FATALERROR("Failed to convert pypath to wchar_t\n");
			return -1;
		}
	    VS("LOADER: Pre-init sys.path is %s\n", pypath);
        PI_Py_SetPath(pypath_w);
    };

    /* Set sys.prefix and sys.exec_prefix using Py_SetPythonHome */
    if (is_py2) {
#ifdef _WIN32
    	if(!pyi_win32_utf8_to_mbs_sfn(pyhome, status->mainpath, PATH_MAX)) {
		    FATALERROR("Failed to convert pyhome to ANSI (invalid multibyte string)\n");
		    return -1;
		}
#else
	    strcpy(pyhome, status->mainpath);
#endif
        VS("LOADER: sys.prefix is %s\n", pyhome);
        PI_Py2_SetPythonHome(pyhome);
    } else {
        /* Decode using current locale */
		if(!pyi_locale_char2wchar(pyhome_w, status->mainpath, PATH_MAX)) {
			FATALERROR("Failed to convert pyhome to wchar_t\n");
			return -1;
		}
        VS("LOADER: sys.prefix is %s\n", status->mainpath);
        PI_Py_SetPythonHome(pyhome_w);
    };

    /* Start python. */
    VS("LOADER: Setting runtime options\n");
    pyi_pylib_set_runtime_opts(status);

	/*
	 * Py_Initialize() may rudely call abort(), and on Windows this triggers the error
	 * reporting service, which results in a dialog box that says "Close program", "Check
	 * for a solution", and also "Debug" if Visual Studio is installed. The dialog box
	 * makes it frustrating to run the test suite.
	 *
	 * For debug builds of the bootloader, disable the error reporting before calling
	 * Py_Initialize and enable it afterward.
	 */

#if defined(_WIN32) && defined(LAUNCH_DEBUG)
	SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
#endif

	VS("LOADER: Initializing python\n");
	PI_Py_Initialize();

#if defined(_WIN32) && defined(LAUNCH_DEBUG)
	SetErrorMode(0);
#endif

	/*
	 * Set sys.path list.
	 * Python's default sys.path is no good - it includes the working directory
	 * and the folder containing the executable. Replace sys.path with only
	 * the paths we want.
	 */
	VS("LOADER: Overriding Python's sys.path\n");
	VS("LOADER: Post-init sys.path is %s\n", pypath);
	if (is_py2) {
#ifdef _WIN32
	    if(!pyi_win32_utf8_to_mbs_sfn(pypath_sfn, pypath, PATH_MAX)) {
			FATALERROR("Failed to convert pypath to ANSI (invalid multibyte string)\n");
		}
	    PI_Py2Sys_SetPath(pypath_sfn);
#else
	    PI_Py2Sys_SetPath(pypath);
#endif
	} else {
	   PI_PySys_SetPath(pypath_w);
	};

    /* Setting sys.argv should be after Py_Initialize() call. */
    if(pyi_pylib_set_sys_argv(status)) {
        return -1;
    }

	/* Check for a python error */
	if (PI_PyErr_Occurred())
	{
		FATALERROR("Error detected starting Python VM.");
		return -1;
	}

	return 0;
}
Exemplo n.º 2
0
void
PI_Py2Sys_SetPath(char * str)
{
    PI_PySys_SetPath((wchar_t *) str);
};