python-pillow / Pillow

Python Imaging Library (Fork)
https://python-pillow.org
Other
12.33k stars 2.24k forks source link

Windows Docker / nanoserver support #8249

Closed structurefall closed 3 months ago

structurefall commented 4 months ago

Everybody's going to love this one. I assure you, I have a good reason for wanting this!

I have a Python 3.10.11 install running on a Windows Docker nanoserver ltsc2022 image.

After installing pillow 10.4.0 via pip, doing import Image from PIL results in the following:

Traceback (most recent call last):
  File "C:\app\__init__.py", line 3, in <module>
    from PIL import Image
  File "C:\Python\Lib\site-packages\PIL\Image.py", line 100, in <module>
    from . import _imaging as core
ImportError: DLL load failed while importing _imaging: The specified procedure could not be found.

It appears to work on a servercore image, so that's the workaround, but this is onerous for us, so I'd like to know what the specific dependency is in the hopes of installing just that on a nanoserver image.

Thanks!

Yay295 commented 4 months ago

Possibly related to #2479.

Yay295 commented 4 months ago

I've also seen mention that nano servers may just not have the functionality to do this, though I'm not sure exactly what is missing. It's unfortunate that the error message doesn't say which DLL it failed to load.

nulano commented 4 months ago

It appears to work on a servercore image, so that's the workaround, but this is onerous for us, so I'd like to know what the specific dependency is in the hopes of installing just that on a nanoserver image.

Yes, we test released wheels using the servercore image: https://github.com/python-pillow/Pillow/blob/f8a9a18e7dc9a4ce67d46509e1a3c37fa1a7d942/.github/workflows/wheels.yml#L217-L223 It is likely that I tested nanoserver when adding this and rejected it due to this error.

The error message "The specified procedure could not be found" is different from the usual "The specified module could not be found", so I'm not sure that you'll just be able to add a dependency. Your error says that a DLL dependency was found, but does not contain all of the required functions.

Nevertheless, I'll take a look with Dependency Walker.

nulano commented 4 months ago

The following dependencies are listed with Dependencies:

C:\Users\Nulano\Downloads\Dependencies_x64_Release> Dependencies.exe -depth 1 -modules C:\Users\Nulano\AppData\Roaming\Python\Python311\site-packages\pil\_imaging.cp311-win_amd64.pyd
[ROOT] _imaging.cp311-win_amd64.pyd : C:\Users\Nulano\AppData\Roaming\Python\Python311\site-packages\pil\_imaging.cp311-win_amd64.pyd
[ApiSetSchema] api-ms-win-crt-heap-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[ApiSetSchema] api-ms-win-crt-stdio-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[ApiSetSchema] api-ms-win-crt-string-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[ApiSetSchema] api-ms-win-crt-runtime-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[ApiSetSchema] api-ms-win-crt-math-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[ApiSetSchema] api-ms-win-crt-utility-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[ApiSetSchema] api-ms-win-crt-convert-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[ApiSetSchema] api-ms-win-crt-environment-l1-1-0.dll : C:\Windows\system32\ucrtbase.dll
[WellKnownDlls] KERNEL32.dll : C:\Windows\system32\kernel32.dll
[WellKnownDlls] USER32.dll : C:\Windows\system32\user32.dll
[WellKnownDlls] GDI32.dll : C:\Windows\system32\gdi32.dll
[WindowsFolder] VCRUNTIME140.dll : C:\Windows\system32\VCRUNTIME140.dll
[NOT_FOUND] python311.dll :
Full list of imported symbols (click to expand) ``` C:\Users\Nulano\Downloads\Dependencies_x64_Release>Dependencies.exe -depth 1 -imports C:\Users\Nulano\AppData\Roaming\Python\Python311\site-packages\pil\_imaging.cp311-win_amd64.pyd [-] Import listing for file : C:\Users\Nulano\AppData\Roaming\Python\Python311\site-packages\pil\_imaging.cp311-win_amd64.pyd Import from module KERNEL32.dll : Function SetEvent Function WaitForSingleObject Function CreateEventA Function TlsAlloc Function TlsGetValue Function TlsSetValue Function GetSystemInfo Function RtlCaptureContext Function RtlLookupFunctionEntry Function RtlVirtualUnwind Function UnhandledExceptionFilter Function SetUnhandledExceptionFilter Function GetCurrentProcess Function TerminateProcess Function IsProcessorFeaturePresent Function InitializeCriticalSectionAndSpinCount Function GetCurrentProcessId Function GetCurrentThreadId Function GetSystemTimeAsFileTime Function DisableThreadLibraryCalls Function InitializeSListHead Function IsDebuggerPresent Function InitializeCriticalSectionEx Function InitializeConditionVariable Function WakeConditionVariable Function SleepConditionVariableCS Function WaitForSingleObjectEx Function SetThreadPriority Function DeleteCriticalSection Function LeaveCriticalSection Function EnterCriticalSection Function CreateFileMappingA Function UnmapViewOfFile Function MapViewOfFile Function GetLastError Function CloseHandle Function WriteFile Function SetFilePointer Function ReadFile Function GetFileSizeEx Function GlobalUnlock Function FreeLibrary Function GlobalLock Function GetProcAddress Function LoadLibraryA Function GetModuleHandleA Function GlobalSize Function Sleep Function QueryPerformanceCounter Import from module USER32.dll : Function GetMessageA Function DispatchMessageA Function GetWindowRect Function EndPaint Function BeginPaint Function LoadCursorA Function GetDC Function FillRect Function GetSystemMetrics Function ShowWindow Function OpenClipboard Function CloseClipboard Function EnumClipboardFormats Function RegisterClassA Function DefWindowProcA Function CreateWindowExA Function TranslateMessage Function GetClipboardData Function LoadIconA Function GetWindowLongPtrA Function SetWindowLongPtrA Function SetForegroundWindow Function InvalidateRect Function RegisterClipboardFormatA Function ReleaseDC Import from module GDI32.dll : Function CreatePalette Function GetSystemPaletteEntries Function SelectPalette Function BitBlt Function CreateCompatibleBitmap Function SelectObject Function SetWinMetaFileBits Function CreateDIBSection Function CreateCompatibleDC Function GdiFlush Function PlayEnhMetaFile Function SetEnhMetaFileBits Function GetStockObject Function GetDIBits Function DeleteEnhMetaFile Function GetDeviceCaps Function DeleteDC Function DeleteObject Function CreateDCA Function RealizePalette Function StretchBlt Function SetDIBColorTable Function StretchDIBits Import from module python311.dll : Function PyList_SetItem Function PyObject_Print Function _Py_TrueStruct Function PyExc_IndexError Function PyUnicode_FromString Function PyExc_TypeError Function _PyObject_New Function PyBytes_FromStringAndSize Function PyObject_Size Function PyBuffer_Release Function PyEval_RestoreThread Function PyExc_RuntimeError Function _PyObject_CallFunction_SizeT Function PySys_GetObject Function PyFile_WriteString Function PyExc_OSError Function PyErr_NoMemory Function PyUnicode_Type Function PySequence_Check Function PyDict_New Function PyCapsule_New Function PyErr_Clear Function _PyObject_CallMethod_SizeT Function PyErr_Print Function PyType_Ready Function PyThreadState_Swap Function PyList_Size Function PyErr_Format Function PyErr_SetFromErrno Function PyModule_Create2 Function PyList_New Function PySequence_Fast Function _PyBytes_Resize Function PyObject_GetBuffer Function PySequence_Size Function PyLong_AsLong Function _PyArg_ParseTuple_SizeT Function PyNumber_AsSsize_t Function PyNumber_Check Function PyIndex_Check Function PyErr_ExceptionMatches Function PyObject_CallFunction Function Py_BuildValue Function PySlice_Unpack Function PySequence_GetItem Function PySlice_Type Function PySlice_AdjustIndices Function PyArg_ParseTuple Function PyExc_MemoryError Function PyObject_CallMethod Function PyLong_AsSsize_t Function PyExc_SystemError Function PyObject_CheckBuffer Function PyModule_AddObject Function PyObject_IsTrue Function PyDict_GetItem Function PyList_GetItem Function PyBytes_Size Function PyTuple_Size Function PyObject_Free Function PyModule_GetDict Function PyTuple_GetItem Function _Py_Dealloc Function PyType_IsSubtype Function PyFloat_Type Function _Py_FalseStruct Function PyExc_ValueError Function PyErr_SetString Function PyFloat_FromDouble Function PyDict_SetItemString Function PyTuple_New Function PyLong_AsLongLong Function _Py_NoneStruct Function PyBytes_AsStringAndSize Function PyFloat_AsDouble Function PyUnicode_AsLatin1String Function PyLong_FromLong Function PyEval_SaveThread Function PyLong_FromSsize_t Function PyErr_Occurred Function PyBytes_AsString Function _PyErr_BadInternalCall Function PyModule_AddIntConstant Function _Py_BuildValue_SizeT Function PyBool_FromLong Function PyThreadState_Get Import from module VCRUNTIME140.dll : Function longjmp Function memmove Function memset Function memcmp Function __C_specific_handler Function __intrinsic_setjmp Function __std_type_info_destroy_list Function memcpy Import from module api-ms-win-crt-heap-l1-1-0.dll : Function _aligned_free Function calloc Function free Function malloc Function _aligned_malloc Function realloc Import from module api-ms-win-crt-stdio-l1-1-0.dll : Function __stdio_common_vsprintf Function __stdio_common_vfprintf Function _lseek Function _write Function __stdio_common_vsscanf Function __stdio_common_vsnprintf_s Function __acrt_iob_func Function fopen Function _get_osfhandle Function fwrite Function fclose Import from module api-ms-win-crt-string-l1-1-0.dll : Function strcmp Function strncmp Function _strdup Function strncpy Import from module api-ms-win-crt-runtime-l1-1-0.dll : Function _beginthreadex Function _initterm Function _initterm_e Function _seh_filter_dll Function _configure_narrow_argv Function exit Function _initialize_narrow_environment Function _cexit Function _execute_onexit_table Function _initialize_onexit_table Function abort Import from module api-ms-win-crt-math-l1-1-0.dll : Function lround Function hypot Function roundf Function round Function floor Function pow Function exp Function log Function atan2 Function sin Function powf Function sqrtf Function log10 Function fmin Function sqrt Function fmax Function cos Function fmod Function ceil Import from module api-ms-win-crt-utility-l1-1-0.dll : Function bsearch Function rand Function qsort Import from module api-ms-win-crt-convert-l1-1-0.dll : Function atoi Import from module api-ms-win-crt-environment-l1-1-0.dll : Function getenv_s Function getenv [-] Import listing done ```

I was unable to figure out the mappings for some of them, but even the KERNEL32.dll imports (which I assume map to KernelBase.dll in servernano) are incomplete; the following symbols are missing (by manually comparing the _imaging imports with kernelbase.dll exports):

CreateFileMappingA (CreateFileMappingW is available)
GlobalLock
GlobalUnlock
RtlCaptureContext
RtlLookupFunctionEntry
RtlVirtualUnwind
WakeConditionVariable

Assuming the api-*.dll files map to ucrtbase.dll, they seem to be fully satisfied.

I was unable to figure out what USER32.dll and GDI.dll map to, but I suspect these are not present at all in nanoserver, so you'd need to compile Pillow without PIL.ImageGrab (and likely more modules, e.g. PIL.ImageDraw).

Also note that we don't support compiling without these modules, and #8211 is open to remove old (and untested) compile flags that potentially could have been used to achieve that.

nulano commented 4 months ago

Doing some grep searches, I can see that you'd need to disable at least the following to avoid some of the symbols above:

So it might actually be easier to keep using servercore.

structurefall commented 4 months ago

Yeah, I definitely don't want to pin us to anything old or unsupported. servercore will work for now, thank you for looking into it!

aclark4life commented 4 months ago

Fascinating issue, thanks @structurefall @nulano

radarhere commented 4 months ago

servercore will work for now, thank you for looking into it!

Does that mean this issue is resolved?