Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyWin32 and Python 3.8.0

Python 3.8.0 has been recently released (on 20191014, and can be downloaded from [Python]: Python 3.8.0).
PyWin32 has builds for it on [PyPI]: pywin32 225 (released on 20190915). Unfortunately, after pip installing, it doesn't work.

Sample:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058631512]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe"
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import win32api
>>> ^Z


[prompt]> "e:\Work\Dev\VEnvs\py_064_03.08.00_test0\Scripts\python.exe"
Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import win32api
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: DLL load failed while importing win32api: The specified module could not be found.
>>> ^Z

Notes:

  • For Python 3.7, I also upgraded my PyWin32 module to the latest, and it works
  • Older PyWin32 versions work on older Python versions (2.7, 3.5, 3.6)
  • Reproducible on 64bit and 32bit
like image 677
CristiFati Avatar asked Oct 30 '19 18:10

CristiFati


1 Answers

Spoiler alert!!!

Applied #2.2. (from below) to the original .whls, and published them on [GitHub]: CristiFati/Prebuilt-Binaries - (master) Prebuilt-Binaries/PyWin32/v225 (win_amd64, win32 for Python 3.8).

After installing (one of) them, existing code should work OOTB (with respect to this issue).

Install steps:

  1. Download the .whl that matches your Python architecture (64bit, 32bit - for more details on getting Python architecture, check [SO]: How do I determine if my python shell is executing in 32bit or 64bit? (@CristiFati's answer) (the question is about OSX, but other platforms are covered as well)), it will most likely be 64bit (win_amd64), from the above URL.
    For example, I downloaded it in L:\Downloads

  2. Invoke the PIP installer on it ([SO]: How to install a package for a specific Python version on Windows 10? (@CristiFati's answer)). Something like:

    (${path_to_your})python.exe -m pip ${path_to_the_downloaded_pywin32_whl}
    

    Example:

    "e:\Work\Dev\VEnvs\py_pc064_03.08.00_test0\Scripts\python.exe" -m pip "L:\Downloads\pywin32-225-cp38-cp38-win_amd64.whl"
    


The problem has been reported on [GitHub]: mhammond/pywin32 - python 3.8.

The above URL references 2 more:

  • [Python 3.8.Docs]: What’s New In Python 3.8 - Changes in the Python API which states (emphasis is mine):

    • DLL dependencies for extension modules and DLLs loaded with ctypes on Windows are now resolved more securely. Only the system paths, the directory containing the DLL or PYD file, and directories added with add_dll_directory() are searched for load-time dependencies. Specifically, PATH and the current working directory are no longer used, and modifications to these will no longer have any effect on normal DLL resolution.
  • [Python 3.Docs]: os.add_dll_directory(path) which states (emphasis still mine):

    This search path is used when resolving dependencies for imported extension modules (the module itself is resolved through sys.path), and also by ctypes.

In the same time, I did some digging of my own and discovered that (for win32api.pyd) it's pywintypes38.dll (which is a dependency for the .pyds) that is not found (I also specified this in a comment on the issue).

Solutions (actually workarounds (more or less) until an official and backwards compatible fix is released):

  1. Force pywintypes38.dll load by importing it (as it's also a Python module and in this scenario it doesn't fall under the above rule) before any PyWin32 module:

    import pywintypes
    import win32api
    

    If working with COM, you'd need import pythoncom

  2. Adding pywin32_system32 to the .dll search paths (following the new model from above). There are multiple ways:

    1. v-python's comment from the issue URL which provides a small snippet (I didn't test it)

    2. I also submitted [GitHub]: mhammond/pywin32 - Support for Python 3.8, where I do everything in the pywin32.pth file ("executed" when the interpreter starts, so no changes needed for existing code). Unfortunately, there is a problem with the AppVeyor automated tests which fail (but for some other reasons), so it has been stuck there for a while. Note that in the meantime, the PR was closed and another (similar) approach was pushed. Note that v226 (released on 20191110) which contains the fix, does not work on VirtualEnv ([SO]: PyWin32 (226) and virtual environments (@CristiFati's answer)).
      Anyway, applying the changes locally (1) (on both my Python VirtualEnvs), solved the problem (on one, and didn't break the other):

      [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058631512]> sopr.bat
      ### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###
      
      [prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" -c "import win32api"
      
      [prompt]> "e:\Work\Dev\VEnvs\py_064_03.08.00_test0\Scripts\python.exe" -c "import win32api"
      
      [prompt]>
      
    3. Other ways like copying the .dlls (e.g. in %SystemRoot%\System32), or symlinking them, but (personally) I wouldn't recommend those



Update #0

[PyPI]: pywin32 227 (which addresses this issue), was published on 20191114!



Footnotes

  • #1: Check [SO]: Run / Debug a Django application's UnitTests from the mouse right click context menu in PyCharm Community Edition? (@CristiFati's answer) (Patching utrunner section) for how to apply patches (on Win).
like image 130
CristiFati Avatar answered Nov 07 '22 16:11

CristiFati