0

I've tried this:

import trio
from gevent import monkey, spawn

monkey.patch_all()

async def async_double(x):
    return 2 * x

def run():
    return trio.run(async_double, 3)

g = spawn(run)
g.join()

But I get an error:

Traceback (most recent call last):
  File "src/gevent/greenlet.py", line 908, in gevent._gevent_cgreenlet.Greenlet.run
  File "/Users/xxx/t.py", line 10, in run
    return trio.run(async_double, 3)
  File "/Users/xxx/Library/Python/3.9/lib/python/site-packages/trio/_core/_run.py", line 1990, in run
    runner = setup_runner(
  File "/Users/xxx/Library/Python/3.9/lib/python/site-packages/trio/_core/_run.py", line 1885, in setup_runner
    io_manager = TheIOManager()
  File "<attrs generated init trio._core._io_kqueue.KqueueIOManager>", line 15, in __init__
    self.__attrs_post_init__()
  File "/Users/xxx/Library/Python/3.9/lib/python/site-packages/trio/_core/_io_kqueue.py", line 33, in __attrs_post_init__
    force_wakeup_event = select.kevent(
AttributeError: module 'select' has no attribute 'kevent'
2023-07-28T21:06:31Z <Greenlet at 0x105d22370: run> failed with AttributeError

I've also tried importing and patching gevent first, but that fails even before running:

from gevent import monkey, spawn
monkey.patch_all()
import trio

Traceback:

  File "/Users/xxx/t.py", line 3, in <module>
    import trio
  File "/Users/xxx/Library/Python/3.9/lib/python/site-packages/trio/__init__.py", line 18, in <module>
    from ._core import (
  File "/Users/xxx/Library/Python/3.9/lib/python/site-packages/trio/_core/__init__.py", line 27, in <module>
    from ._run import (
  File "/Users/xxx/Library/Python/3.9/lib/python/site-packages/trio/_core/_run.py", line 2458, in <module>
    raise NotImplementedError("unsupported platform")
NotImplementedError: unsupported platform

I think I managed to get the first approach (importing trio first) working at times (but that code was a little different and a lot more complex), but I want to know if that was just lucky and would have issues later on.

This is on MacOS, but it needs to be cross platform.

Edit: Note that "This is impossible, dont even try" is a completely acceptable answer, as long as it is properly motivated :)

Edit: My end goal is to allow users of Locust (a load test framework which uses gevent for concurrency) to also run things that depend on trio (like for example Playwright)

Cyberwiz
  • 11,027
  • 3
  • 20
  • 40
  • Looks like gevent patching of thread (on my windows machine) does not play well with the threading patch. Adding `monkey.patch_all(thread=False)` causes the example to succeed. That said, my initial error was different from yours. I feel as though these libraries conflict with eachother at a core level, where each is relying on low level implementation details of the standard libraries, which means patching their implementations leads to incompatibilities. – flakes Aug 02 '23 at 03:43

2 Answers2

1

If your goal is to run async code from sync code, you can use the greenback module.

If you want to (or have to) go the "patch things" route, there's a rudimentary Trio-compatible equivalent to gevent, appropriately called aevent, at https://github.com/M-o-a-T/aevent – emphasis on "rudimentary".

I strongly recommend to not even think of trying to gevent-monkey-patch anything in a Trio project (or asyncio, for that matter).

Matthias Urlichs
  • 2,301
  • 19
  • 29
  • My goal is to allow users of Locust (a load test framework which uses gevent for concurrency) to also run things that depend on trio (like Playwright). I cant remove gevent, but greenback might be interesting. Can you explain/point to some resource that explains what will break if I import trio and then apply gevents monkey patch? – Cyberwiz Aug 04 '23 at 19:05
  • Huh. I just realized something. Playwright doesnt actually use trio, it just imports pyee which happens to also import trio (but probably doesnt use it). This is probably the reason why importing trio before monkey patching worked for me when running Locust, but caused issues the above example. – Cyberwiz Aug 04 '23 at 19:29
0

I managed to get the first approach (importing trio first) working at times ..., but I want to know if that was just lucky and would have issues later on.

Yes, it would have issues on macOS (fine for win32 and linux) if actually using trio.

On macOS, trio _run.py enters kqueue block with import KqueueIOManager as TheIOManager.
KqueueIOManager calls select.kevent, which is removed with kqueue in the select patch.
Removal of kqueue if patch before trio causes _run.py to enter else block with that raise.

You can skip it and let trio continue to use the blocking kqueue by not doing aggressive patch:

from gevent import monkey, spawn
# monkey.patch_all()                # Change this to
monkey.patch_all(aggressive=False)  # either this
# monkey.patch_all(select=False)    # or not patch select at all
import trio
aaron
  • 39,695
  • 6
  • 46
  • 102