ようやく謎が解けた
pywin32 の公式リポジトリ
"system wide" じゃなくてユーザ権限でインストールしたいので、それでは全然解決にならないからそれはやりたくない。
また、前回も書いた通り、このスクリプトユーザ権限で
上記は現時点のバージョン b300 で試した結果なのだが、具体的には以下の箇所。
どうも、-destination オプションで %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\\site-packages" を与えてやる必要があるらしい。
すると以下のようになった。
get_system_dir() の結果 C:\WINDOWS\system32
sys.prefix の結果 C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0
を調べて、書き込み権限がないために失敗している。
ということで、一旦、最終目標は諦めて、公式サイトに書いてある通り、素直に管理者権限で cmd を起こして
ちゃんと、Microsoft Store 版の python でも import win32api 出来るじゃん!
しかし、そうじゃない。
"system wide" じゃなくユーザ権限のみで動かしたいので、全然解決になってない。
でもとりあえず、import win32api 出来ることは確認できたので、一歩前進。
上記の操作で "system wide" に設定されてしまったので、元に戻すため以下のようにしておいた。
さて、先程のスクリプトであるが、
実際、
つまり、
さて、問題の win32api.pyd なのだが
一方、
hasattr(sys, "frozen") が真なら
偽なら、
ところが、これも frozen、非 frozen 共に以下の有様。
sys.path を確認してみると
これは、site モジュールの説明によると、site-package 以下の .pth ファイルの内容が反映されているらしい。
以下に、pywin32 が生成した .pth があり以下のような内容だった。
これに pywin32_system32 を追加して、以下のように変更。
結果、以下のようになった。
pywin32 の公式リポジトリ
- GitHub / mhammond / pywin32
Installing via PIPみたいなことが書いてある。
---------------------
You can install pywin32 via pip:
| pip install pywin32
Note that if you want to use pywin32 for "system wide" features, such as registering COM objects or implementing Windows Services, then you must run the following command from an elevated command prompt:
| python Scripts/pywin32_postinstall.py -install
"system wide" じゃなくてユーザ権限でインストールしたいので、それでは全然解決にならないからそれはやりたくない。
また、前回も書いた通り、このスクリプトユーザ権限で
CD %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37" python Scripts/pywin32_postinstall.py -installみたいにして実行しても
Parsed arguments are: Namespace(destination='C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\\Lib\\site-packages', install=True, quiet=False, remove=False, silent=False, wait=None) Traceback (most recent call last): File "Scripts/pywin32_postinstall.py", line 630, in <module> install(args.destination) File "Scripts/pywin32_postinstall.py", line 331, in install LoadSystemModule(lib_dir, "pywintypes") File "Scripts/pywin32_postinstall.py", line 171, in LoadSystemModule mod = importlib.util.module_from_spec(spec) File "<frozen importlib._bootstrap>", line 583, in module_from_spec File "<frozen importlib._bootstrap_external>", line 1043, in create_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed ImportError: DLL load failed: 指定されたモジュールが見つかりません。みたいにエラーになる。
上記は現時点のバージョン b300 で試した結果なのだが、具体的には以下の箇所。
- pywin32 / blob / b300 / pywin32_postinstall.py: Line 171
$ diff -c pywin32_postinstall{,2}.py *** pywin32_postinstall.py 2020-11-17 16:04:01.024713700 +0900 --- pywin32_postinstall2.py 2020-11-17 19:56:01.093931600 +0900 *************** *** 168,173 **** --- 168,174 ---- filename = os.path.join(lib_dir, "pywin32_system32", filename) loader = importlib.machinery.ExtensionFileLoader(modname, filename) spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=filename) + print("\n","="*40,"\n",spec,"\n","="*40,"\n") mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod)すると以下のようになった。
>python Scripts/pywin32_postinstall2.py -install Parsed arguments are: Namespace(destination='C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\\Lib\\site-packages', install=True, quiet=False, remove=False, silent=False, wait=None) ======================================== ModuleSpec(name='pywintypes', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x00000284544848C8>, origin='C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\\Lib\\site-packages\\pywin32_system32\\pywintypes37.dll') ======================================== Traceback (most recent call last): File "Scripts/pywin32_postinstall2.py", line 631, in <module> install(args.destination) File "Scripts/pywin32_postinstall2.py", line 332, in install LoadSystemModule(lib_dir, "pywintypes") File "Scripts/pywin32_postinstall2.py", line 172, in LoadSystemModule mod = importlib.util.module_from_spec(spec) File "<frozen importlib._bootstrap>", line 583, in module_from_spec File "<frozen importlib._bootstrap_external>", line 1043, in create_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed ImportError: DLL load failed: 指定されたモジュールが見つかりません。pywintypes37.dll はユーザー環境に入っているが "system wide" には入ってないので、当然見つかるはずがない。
どうも、-destination オプションで %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\\site-packages" を与えてやる必要があるらしい。
すると以下のようになった。
>python Scripts/pywin32_postinstall2.py -install -destination %CD%\site-packages Parsed arguments are: Namespace(destination='C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages', install=True, quiet=False, remove=False, silent=False, wait=None) ======================================== ModuleSpec(name='pywintypes', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x0000020DE2044988>, origin='C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages\\pywin32_system32\\pywintypes37.dll') ======================================== ======================================== ModuleSpec(name='pythoncom', loader=<_frozen_importlib_external.ExtensionFileLoader object at 0x0000020DE2068248>, origin='C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages\\pywin32_system32\\pythoncom37.dll') ======================================== Traceback (most recent call last): File "Scripts/pywin32_postinstall2.py", line 631, in <module> install(args.destination) File "Scripts/pywin32_postinstall2.py", line 380, in install "You don't have enough permissions to install the system files") RuntimeError: You don't have enough permissions to install the system filesprint debug 用に 171 行目に 1 行増やしたので、これは以下の箇所である。
- pywin32 / blob / b300 / pywin32_postinstall.py: Line 379
- pywin32 / blob / b300 / pywin32_postinstall.py: Line 340
get_system_dir() の結果 C:\WINDOWS\system32
sys.prefix の結果 C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0
を調べて、書き込み権限がないために失敗している。
ということで、一旦、最終目標は諦めて、公式サイトに書いてある通り、素直に管理者権限で cmd を起こして
CD %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37" python Scripts/pywin32_postinstall.py -install -destination %CD%\site-packagesみたいにしてみると
Parsed arguments are: Namespace(destination='C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages', install=True, quiet=False, remove=False, silent=False, wait=None) Copied pythoncom37.dll to C:\WINDOWS\system32\pythoncom37.dll Copied pywintypes37.dll to C:\WINDOWS\system32\pywintypes37.dll Registered: Python.Interpreter Registered: Python.Dictionary Registered: Python -> Software\Python\PythonCore\3.7\Help[None]=None -> Software\Python\PythonCore\3.7\Help\Pythonwin Reference[None]='C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages\\PyWin32.chm' Pythonwin has been registered in context menu Creating directory C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32com\gen_py Can't install shortcuts - 'C:\\Users\\kou\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Python 3.7' is not a folder The pywin32 extensions were successfully installed.みたいになって、この状態であれば import win32api 可能になった。
ちゃんと、Microsoft Store 版の python でも import win32api 出来るじゃん!
しかし、そうじゃない。
"system wide" じゃなくユーザ権限のみで動かしたいので、全然解決になってない。
でもとりあえず、import win32api 出来ることは確認できたので、一歩前進。
上記の操作で "system wide" に設定されてしまったので、元に戻すため以下のようにしておいた。
CD %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37" python Scripts/pywin32_postinstall.py -remove -destination %CD%\site-packages
さて、先程のスクリプトであるが、
- pywin32 / blob / b300 / pywin32_postinstall.py: Line 331-333
LoadSystemModule(lib_dir, "pywintypes") LoadSystemModule(lib_dir, "pythoncom") import win32apiのような事をしていて、要するに "system wide" に設定せずとも
- pythoncom37.dll
- pywintypes37.dll
実際、
import site from ctypes import * PyDLL(site.USER_SITE+r"\pywin32_system32\pywintypes37.dll") PyDLL(site.USER_SITE+r"\pywin32_system32\pythoncom37.dll") import win32apiみたいにすると、きちんと import win32api できた。
つまり、
- %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32\win32api.pyd"
- %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\pywin32_system32"
さて、問題の win32api.pyd なのだが
- pywin32 /blob /b300 / setup.py: Line 1464-1471
- pywin32/blob/b300/win32/src/win32api_display.cpp
- pywin32/blob/b300/win32/src/win32apimodule.cpp
- pythoncom37.dll
- pywintypes37.dll
一方、
- pywin32 / blob / b300 / win32 / Lib / pywintypes.py
hasattr(sys, "frozen") が真なら
- sys.path
偽なら、
- _win32sysloader.GetModuleFilename(filename)
- _win32sysloader.LoadModule(filename)
- os.path.join(sys.prefix, filename)
- os.path.join(os.path.dirname(__file__), filename)
- os.path.join(distutils.sysconfig.get_python_lib(plat_specific=1), "pywin32_system32", filename)
ところが、これも frozen、非 frozen 共に以下の有様。
>python Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 16:30:00) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import pywintypes Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32\lib\pywintypes.py", line 105, in <module> __import_pywin32_system_module__("pywintypes", globals()) File "C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32\lib\pywintypes.py", line 87, in __import_pywin32_system_module__ raise ImportError("No system module '%s' (%s)" % (modname, filename)) ImportError: No system module 'pywintypes' (pywintypes37.dll)
>python Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 16:30:00) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> setattr(sys,"frozen",True) >>> import win32api Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: DLL load failed: 指定されたモジュールが見つかりません。 >>> import pywintypes Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32\lib\pywintypes.py", line 105, in <module> __import_pywin32_system_module__("pywintypes", globals()) File "C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32\lib\pywintypes.py", line 38, in __import_pywin32_system_module__ raise ImportError("Module '%s' isn't in frozen sys.path %s" % (modname, sys.path)) ImportError: Module 'pywintypes' isn't in frozen sys.path ['', 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\\python37.zip', 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\\DLLs', 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\\lib', 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0', 'C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages', 'C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages\\win32', 'C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages\\win32\\lib', 'C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages\\Pythonwin', 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\\lib\\site-packages']
sys.path を確認してみると
>python Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 16:30:00) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> for i in sys.path: print(i) ... C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\python37.zip C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\DLLs C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0 C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32 C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\win32\lib C:\Users\kou\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\Pythonwin C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib\site-packagesみたいになってて、pywin32 の設定らしきパスがどこからか入り込んできてきちんと登録されているのに、なぜか、
- %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\pywin32_system32"
これは、site モジュールの説明によると、site-package 以下の .pth ファイルの内容が反映されているらしい。
以下に、pywin32 が生成した .pth があり以下のような内容だった。
%USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\pywin32.pth"
# .pth file for the PyWin32 extensions win32 win32\lib Pythonwin # And some hackery to deal with environments where the post_install script # isn't run. import pywin32_bootstrap
%USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages\pywin32.pth"
# .pth file for the PyWin32 extensions win32 win32\lib Pythonwin pywin32_system32 # And some hackery to deal with environments where the post_install script # isn't run. import pywin32_bootstrap
結果、以下のようになった。
>python Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 16:30:00) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> setattr(sys,"frozen",True) >>> import win32api Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: DLL load failed: 指定されたモジュールが見つかりません。 >>> import pywintypes >>> import win32api >>> win32api <module 'win32api' from 'C:\\Users\\kou\\AppData\\Local\\Packages\\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\\LocalCache\\local-packages\\Python37\\site-packages\\win32\\win32api.pyd'>
.pth に pywin32_system32 を追加した状態で frozen しておけば、import pywintypes 出来る。
それでも import win32api には失敗するが、import pywintypes が成功してれば、pythoncom37.dll と pywintypes37.dll の読み込みは完了しているので、 import win32api 可能になるという結果。
惜しい。
ということで、pythoncom37.dll と pywintypes37.dll を適当な関係してそうなフォルダにコピーして確認してみた所以下のような結果になった。
なお site.USER_SITE は今の場合
統一感ねぇな、何だよこれ!?
って感じだが、とりあえず、上記の場所に、pythoncom37.dll と pywintypes37.dll を置いておけば Microsoft Store 版の Python でも、とりあえず import win32api が出来ることが分かった。
さて、本家に報告したいのだが、英語、面倒臭い。
今日は流石に力尽きたので、後日余力がある時に頑張って報告かなぁ。
それでも import win32api には失敗するが、import pywintypes が成功してれば、pythoncom37.dll と pywintypes37.dll の読み込みは完了しているので、 import win32api 可能になるという結果。
惜しい。
ということで、pythoncom37.dll と pywintypes37.dll を適当な関係してそうなフォルダにコピーして確認してみた所以下のような結果になった。
PATH | win32api | pywintypes |
---|---|---|
site.USER_SITE | × | × |
site.USER_SITE+r"\pythonwin" | × | × |
site.USER_SITE+r"\win32" | ○ | × |
site.USER_SITE+r"\win32\lib" | × | ○ |
- %USERPROFILE%"\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.7_qbz5n2kfra8p0\LocalCache\local-packages\Python37\site-packages
統一感ねぇな、何だよこれ!?
って感じだが、とりあえず、上記の場所に、pythoncom37.dll と pywintypes37.dll を置いておけば Microsoft Store 版の Python でも、とりあえず import win32api が出来ることが分かった。
さて、本家に報告したいのだが、英語、面倒臭い。
今日は流石に力尽きたので、後日余力がある時に頑張って報告かなぁ。
タグ
コメントをかく