gh-89545: Adds internal _wmi module on Windows for directly querying OS properties#96289
gh-89545: Adds internal _wmi module on Windows for directly querying OS properties#96289zooba merged 20 commits into
Conversation
…rying OS properties
vstinner
left a comment
There was a problem hiding this comment.
Nice enhancement! Some remarks.
Sorry, something went wrong.
Co-authored-by: Victor Stinner <vstinner@python.org>
I think the most straight-froward pipe-based implementation that supports cancel via Ctrl+C is to use a named pipe. For the read side, call |
Sorry, something went wrong.
|
Note that the There's no significant performance cost if calling Footnotes
|
Sorry, something went wrong.
Co-authored-by: Eryk Sun <eryksun@gmail.com>
I did remove the places I found that may trigger this on normal load, but the point is well made. However, I don't think we could reliably handle In any case, I think all that belongs in a new issue. At worst, we can always make |
Sorry, something went wrong.
Currently Python's standard library cannot use ctypes could potentially be used to call
Compared to a control event, it's a lot harder to create a hidden window, run a message loop, and handle |
Sorry, something went wrong.
|
If I substitute "onecore_apiset.lib" for "ole32.lib" in "PCbuild/pyproject.props", "_wmi.pyd" and "_ctypes.pyd" end up linking to "api-ms-win-core-com-l1-1-0.dll". This API set is implemented by "combase.dll", which doesn't immediately load "user32.dll". That said, "user32.dll" still gets loaded as soon as FWIW, linking with "onecore_apiset.lib" does solve the ctypes problem. I think a purely console or purely background script should at least be able to set a handler via |
Sorry, something went wrong.
If it's an issue, I suggest to call the _wmi module in a subprocess in the platform module. I don't think that the performance of platform module is critical and this module already spawns subprocesses to retrieve some data. We just have to make sure that the result is cached to only do that once ;-) I don't expect the Windows version to change while a process is running. |
Sorry, something went wrong.
Sorry if the point was lost in side discussions, but the main concern was the change to use |
Sorry, something went wrong.
Let's hope not 😆
Did we ever document the |
Sorry, something went wrong.
|
It's documented, but it's documented as being unreliable. So I removed the WMI check in |
Sorry, something went wrong.
If this is implemented, I suggest using multiprocessing. It implements If importing def _wmi_query(table, *keys):
table = {
"OS": "Win32_OperatingSystem",
"CPU": "Win32_Processor",
}[table]
query = "SELECT {} FROM {}".format(",".join(keys), table)
if _wmi._isguiprocess():
data = _wmi.exec_query(query)
else:
import multiprocessing
p = multiprocessing.Pool(1)
try:
data = p.apply(_wmi.exec_query, (query,))
finally:
p.close()
split_data = (i.partition("=") for i in data.split("\0"))
dict_data = {i[0]: i[2] for i in split_data}
return (dict_data[k] for k in keys)A more elaborate implementation would only close the process pool after it hasn't been used for a minute or so, like how COM implements the local server context. |
Sorry, something went wrong.
We can recommend it if people run into trouble. But I don't see any reason to do it preemptively. This is far from the only thing likely to load user32, and it should only impact people who are already doing things that we don't provide for them. Using the |
Sorry, something went wrong.
|
The effect of loading user32.dll and converting the current thread to a GUI thread is not trivial. Would it make sense to document the change in the sys.getwindowsversion() documentation? |
Sorry, something went wrong.
Not now that It probably makes more sense to document it in |
Sorry, something went wrong.
Co-authored-by: Eryk Sun <eryksun@gmail.com>
Currently the These three control events could be supported if the This is all for naught, however, whenever "python[w].exe" gets executed by "py[w].exe" or "venv[w]launcher.exe". The behavior of the launchers is probably worth fixing, but it's not critical. They're primarily intended for development, not deployment of applications and services. "py[w].exe" and "venvwlauncher.exe" load "user32.dll". Since they don't create a hidden window that handles Also, the control handler for the launchers returns A simple way to handle these cases is to remove the child process from the job object when either the session is known to be ending or the console window/tab is closing. In these cases, both the launcher and Python either have to exit on their own or eventually get terminated, so coupling them with a job object no longer matters. |
Sorry, something went wrong.
Basically, you mean it's to handle the signals and pass them along correctly. That's likely true, but it's not really that simple. The job object is already relied upon for termination by PID, so we need to keep the job object. In any case, definitely not part of this change. So I'll merge what is here and we can figure out termination edge cases in all our other mixed up stuff separately. (I'm honestly inclined to just always load user32 and run the loop to handle it, apart from the performance overhead that entails...) |
Sorry, something went wrong.
⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️Hi! The buildbot AMD64 Windows10 3.x has failed when building commit de33df2. What do you need to do:
You can take a look at the buildbot page here: https://buildbot.python.org/all/#builders/146/builds/3535 Summary of the results of the build (if available): Click to see traceback logsremote: Enumerating objects: 34, done.
remote: Counting objects: 3% (1/31)
remote: Counting objects: 6% (2/31)
remote: Counting objects: 9% (3/31)
remote: Counting objects: 12% (4/31)
remote: Counting objects: 16% (5/31)
remote: Counting objects: 19% (6/31)
remote: Counting objects: 22% (7/31)
remote: Counting objects: 25% (8/31)
remote: Counting objects: 29% (9/31)
remote: Counting objects: 32% (10/31)
remote: Counting objects: 35% (11/31)
remote: Counting objects: 38% (12/31)
remote: Counting objects: 41% (13/31)
remote: Counting objects: 45% (14/31)
remote: Counting objects: 48% (15/31)
remote: Counting objects: 51% (16/31)
remote: Counting objects: 54% (17/31)
remote: Counting objects: 58% (18/31)
remote: Counting objects: 61% (19/31)
remote: Counting objects: 64% (20/31)
remote: Counting objects: 67% (21/31)
remote: Counting objects: 70% (22/31)
remote: Counting objects: 74% (23/31)
remote: Counting objects: 77% (24/31)
remote: Counting objects: 80% (25/31)
remote: Counting objects: 83% (26/31)
remote: Counting objects: 87% (27/31)
remote: Counting objects: 90% (28/31)
remote: Counting objects: 93% (29/31)
remote: Counting objects: 96% (30/31)
remote: Counting objects: 100% (31/31)
remote: Counting objects: 100% (31/31), done.
remote: Compressing objects: 5% (1/19)
remote: Compressing objects: 10% (2/19)
remote: Compressing objects: 15% (3/19)
remote: Compressing objects: 21% (4/19)
remote: Compressing objects: 26% (5/19)
remote: Compressing objects: 31% (6/19)
remote: Compressing objects: 36% (7/19)
remote: Compressing objects: 42% (8/19)
remote: Compressing objects: 47% (9/19)
remote: Compressing objects: 52% (10/19)
remote: Compressing objects: 57% (11/19)
remote: Compressing objects: 63% (12/19)
remote: Compressing objects: 68% (13/19)
remote: Compressing objects: 73% (14/19)
remote: Compressing objects: 78% (15/19)
remote: Compressing objects: 84% (16/19)
remote: Compressing objects: 89% (17/19)
remote: Compressing objects: 94% (18/19)
remote: Compressing objects: 100% (19/19)
remote: Compressing objects: 100% (19/19), done.
remote: Total 34 (delta 12), reused 16 (delta 12), pack-reused 3
From https://github.com/python/cpython
* branch main -> FETCH_HEAD
Note: checking out 'de33df27aaf930be6a34027c530a651f0b4c91f5'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at de33df2... gh-89545: Updates platform module to use new internal _wmi module on Windows to directly query OS properties (GH-96289)
Switched to and reset branch 'main'
Could Not Find D:\buildarea\3.x.bolen-windows10\build\Lib\*.pyc
The system cannot find the file specified.
Could Not Find D:\buildarea\3.x.bolen-windows10\build\PCbuild\python*.zip
Could Not Find D:\buildarea\3.x.bolen-windows10\build\Lib\*.pyc
The system cannot find the file specified.
Could Not Find D:\buildarea\3.x.bolen-windows10\build\PCbuild\python*.zip |
Sorry, something went wrong.
|
I'm on the failure |
Sorry, something went wrong.
edited by bedevere-bot
LoadingUh oh!
There was an error while loading. Please reload this page.
Copy link Copy MarkdownSorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.