Pywin32 and Python 3.8.0

PyWin32 and Python 3.8.0

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).

Using pywin32 in a GitLab CI YML file - getting error on pip install

While the python:3.8.0 image has a windows architecture available, it looks like it's pulling the linux version from that tag. You can test this by adding the command uname -srm to the first line of your test scripts.

I wasn't able to get a windows docker image for python running on a shared runner, but I was able to install python 3.8 on a runner with the following minimal .gitlab-ci.yml:

test:
before_script:
- Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
- choco install python3 --version=$PYTHON_VERSION --yes --force --no-progress
- refreshenv
script:
- python -V
- python -m pip install --upgrade pip
- python -m pip install pywin32
variables:
PYTHON_VERSION: "3.8"
tags:
- windows

PyWin32 (226) and virtual environments

Note: I branched this answer (and also the question) from [SO]: PyWin32 and Python 3.8.0 (@CristiFati's answer), as it's a different issue. You might want to check that one before going further.

After some digging, it turns out it's a VirtualEnv bug (or at least, that's how I see things, because VirtualEnv's site.py doesn't contain getsitepackages - although it was present in Python's site.py since v2.7).
There are several issues (that were) open revolving this absence (e.g. [GitHub]: pypa/virtualenv - site.getsitepackages() missing), but they appear to be closed without a fix (many of them due to inactivity). Also, [GitHub]: [WIP] The next-gen virtualenv (rewrite) which is a big refactor, doesn't seem to address it.

Recap: this error (in VirtualEnv context):

  • Also applies to other Python versions (I can confirm for v3.7.3 (32bit))

  • Happens every time when the interpreter starts

In conclusion, do not install PyWin32 226 in (VirtualEnv) virtual environments, as they will end up in a broken state!

PyWin32 (official .whls) "compatibility table" (didn't check Anaconda (or other such tools)):

  • "Normal" (official) Python installations:

    • v226 is OK
  • VirtualEnvs (and also Python's standard venvs):

    • v225 is OK

    • For Python 3.8.0, [GitHub]: CristiFati/Prebuilt-Binaries - (master) Prebuilt-Binaries/PyWin32/v225 should be used

Submitted [GitHub]: mhammond/pywin32 - Workaround for virtual environments (VirtualEnv) (merged on 20191114). Applying the changes locally (check the referenced question for details on how to do it), fixed it:

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

[prompt]> ".\venv_py_064_030800\Scripts\python.exe" -m pip list
Package Version
---------- -------
pip 19.3.1
pywin32 226
setuptools 41.6.0
wheel 0.33.6

[prompt]> ".\venv_py_064_030800\Scripts\python.exe" -c "import win32api"

[prompt]>


Update #0

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

ModuleNotFoundError: No module named 'pywin32'

There is no module by name pywin32 in pywin32 package. You need to import the win32com.client in your code.
import win32com.client as win32

Trying to use win32ui with pywin32 gives: A dynamic link library (DLL) initialization routine failed

Update

Applied the (below) fix (and a couple of more) to the original sources, built them, and uploaded the .whls to [GitHub]: CristiFati/Prebuilt-Binaries - (master) Prebuilt-Binaries/PyWin32/v228.
But, since this bug is kind of a "deal breaker" (and there are 4+ months since v228 was released), I'm expecting v229 very soon (in the next days or so).

Check the Install steps section from (the beginning of) [SO]: PyWin32 and Python 3.8.0 (@CristiFati's answer) for details on how to install the .whls.


It's constantly reproducible on:

  • Python 3.9 64bit and 32bit (works on older versions)

  • PyWin32 228 (and older)

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

[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.09.00_test0\Scripts\python.exe"
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import win32ui
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "c:\Install\pc064\Python\Python\03.09.00\Lib\ctypes\__init__.py", line 374, in __init__
self._handle = _dlopen(self._name, mode)
OSError: [WinError 1114] A dynamic link library (DLL) initialization routine failed
>>> import win32api

I did some debugging (created a VStudio 2015 solution (with 2 projects: for Python 3.9 and Python 3.8) for win32ui), and it turns out it's an Access Violation (segfault).
The "best" part is that it's occurring before DllMain.

One of the last lines that I could get the debugger in, was [GitHub]: mhammond/pywin32 - (b228) pywin32/Pythonwin/win32RichEdit.cpp#225:

PyCCtrlView_Type PyCRichEditView::type("PyCRichEditView", &PyCCtrlView::type, &PyCRichEditCtrl::type,
RUNTIME_CLASS(CRichEditView), sizeof(PyCRichEditView),
PYOBJ_OFFSET(PyCRichEditView), PyCRichEditView_methods,
GET_PY_CTOR(PyCRichEditView));

This is a static member. Since the 2nd and 3rd arguments are also static members (wasn't paying attention to the fact that they're pointers), I thought it was [ISOCPP]: What’s the “static initialization order ‘fiasco’ (problem)”?, and I chased some ghosts.

Anyway, today I noticed [GitHub]: mhammond/pywin32 - Ensure we hold the GIL as win32ui initializes and calls back into Python (and from there [GitHub]: mhammond/pywin32 - Import win32ui broken on Python 3.9 that it's addressing).

Applying the patch, fixes the problem:

[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.09.00_test0\Scripts\python.exe"
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import win32ui
>>> import win32api

Error when installing pywin32 (on Ubuntu)

The pywin32 and pypiwin32 is "Python extensions for Microsoft Windows Provides access to much of the Win32 API, the ability to create and use COM objects, and the Pythonwin environment."

One supported OS is Microsoft Windows, because you can access the Win32 API only from Windows.


Source: https://pypi.org/project/pywin32/



Related Topics



Leave a reply



Submit