Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
dlech committed May 24, 2024
1 parent ef0723f commit 2b48574
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 11 deletions.
7 changes: 6 additions & 1 deletion bleak/backends/winrt/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,16 @@ async def assert_mta() -> None:
Asserts that the current apartment type is MTA.
Raises:
BleakError: If the current apartment type is not MTA.
BleakError:
If the current apartment type is not MTA and there is no Windows
message loop running.
.. versionadded:: 0.22
.. versionchanged:: unreleased
Function is now async and will not raise if the current apartment type
is STA and the Windows message loop is running.
"""
if hasattr(allow_sta, "_allowed"):
return
Expand Down
43 changes: 33 additions & 10 deletions docs/troubleshooting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,32 @@ Not working when threading model is STA

Packages like ``pywin32`` and it's subsidiaries have an unfortunate side effect
of initializing the threading model to Single Threaded Apartment (STA) when
imported. This causes async WinRT functions to never complete. because there
isn't a message loop running. Bleak needs to run in a Multi Threaded Apartment
(MTA) instead (this happens automatically on the first WinRT call).
imported. This causes async WinRT functions to never complete if Bleak is being
used in a console application (no Windows graphical user interface). This is
because there isn't a Windows message loop running to handle async callbacks.
Bleak, when used in a console application, needs to run in a Multi Threaded
Apartment (MTA) instead (this happens automatically on the first WinRT call).

Bleak should detect this and raise an exception with a message similar to::

Thread is configured for Windows GUI but callbacks are not working.

To work around this, you can use one of the utility functions provided by Bleak.
You can tell a ``pywin32`` package caused the issue by checking for
``"pythoncom" in sys.modules``. If it is there, then likely it triggered the
problem. You can avoid this by setting ``sys.coinit_flags = 0`` before importing
any package that indirectly imports ``pythoncom``. This will cause ``pythoncom``
to use the default threading model (MTA) instead of STA.

Example::

import sys
sys.coinit_flags = 0 # 0 means MTA

import win32com # or any other package that causes the issue


If the issue was caused by something other than the ``pythoncom`` module, there
are a couple of other helper functions you can try.

If your program has a graphical user interface and the UI framework *and* it is
properly integrated with asyncio *and* Bleak is not running on a background
Expand All @@ -201,14 +218,20 @@ thread then call ``allow_sta()`` before calling any other Bleak APis::
# can safely ignore
pass

The more typical case, though, is that some library has imported something like
``win32com`` which breaks Bleak. In this case, you can uninitialize the threading
model like this::
The more typical case, though, is that some library has imported something similar
to ``pythoncom`` with the same unwanted side effect of initializing the main
thread of a console application to STA. In this case, you can uninitialize the
threading model like this::

import win32com # this sets current thread to STA :-(
from bleak.backends.winrt.util import uninitialize_sta
import naughty_module # this sets current thread to STA :-(

uninitialize_sta() # undo the unwanted side effect
try:
from bleak.backends.winrt.util import uninitialize_sta

uninitialize_sta() # undo the unwanted side effect
except ImportError:
# not Windows, so no problem
pass


--------------
Expand Down

0 comments on commit 2b48574

Please sign in to comment.