Почему pywintypes cra sh при запуске из двоичного файла py2exe? - PullRequest
0 голосов
/ 05 мая 2020

Я использую следующую версию Python:

>python --version
Python 3.7.4

У меня установлены следующие пакеты через pip:

>pip list
Package        Version
-------------- -----------
-penpyxl       3.0.3
-xpython       4.0.6
altgraph       0.16.1
comtypes       0.6.2
et-xmlfile     1.0.1
future         0.18.2
hexdump        3.3
jdcal          1.4.1
numpy          1.17.1
pefile         2019.4.18
Pillow         6.1.0
pip            19.0.3
py2exe         0.9.3.2
PyInstaller    3.5
pyodbc         4.0.30
pythonnet      2.4.0
pywin32        227
pywin32-ctypes 0.2.0
setuptools     40.8.0

Я использую win32com.client в мой код. Запуск из командной строки работает нормально, но при запуске из двоичного файла py2exe я получаю следующую ошибку:

>dist\testcom.exe
Fatal Python error: pywintypes: can not setup interpreter state, as current state is invalid

Ошибка возникает из pywintypes.py, который содержит код, импортирующий DLL. Я упростил код до следующего фрагмента:

import imp

pywintypes = imp.load_dynamic(
    "pywintypes",
    r"C:\Python37\lib\site-packages\pywin32_system32\pywintypes37.dll",
)

Этот код отлично работает в интерпретаторе, но выдает ошибку при запуске из двоичного файла py2exe.

При поиске ошибки в Google , Я нашел следующий код на github :

void PyWinInterpreterState_Ensure()
{
    if (PyWin_InterpreterState==NULL) {
        PyThreadState *threadStateSave = PyThreadState_Swap(NULL);
        if (threadStateSave==NULL)
            Py_FatalError("pywintypes: can not setup interpreter state, as current state is invalid");

        PyWin_InterpreterState = threadStateSave->interp;
        PyThreadState_Swap(threadStateSave);
    }
    // Save the main thread's state in the TLS map, but not owned.
    ThreadData *pData = (ThreadData *)LocalAlloc(LMEM_ZEROINIT, sizeof(ThreadData));
    if (!pData)
        Py_FatalError("Out of memory allocating thread state.");
    TlsSetValue(dwTlsIndex, pData);
    pData->ts = PyThreadState_Swap(NULL);
    PyThreadState_Swap(pData->ts);
    pData->owned = FALSE;
}

Итак, мой вопрос: есть ли способ заставить это работать с py2exe? Могу ли я сделать что-то со стороны скрипта перед загрузкой?

EDIT: Это мой установочный скрипт, который не делает ничего необычного:

from distutils.core import setup
import py2exe

setup(
    name="testcom",
    options={
        "py2exe": {
            "compressed": True,
            "bundle_files": 1,
        }
    },
    console=["testcom.py"],
)
...