Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import fails with dnspython[doh,trio]: module 'eventlet.green.select' has no attribute 'epoll' #805

Open
ecederstrand opened this issue Jul 11, 2023 · 16 comments

Comments

@ecederstrand
Copy link

I installed eventlet and dnspython with some extensions (dnspython[doh,trio]) and am getting this stack trace when importing:

>>> import eventlet
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "lib/python3.9/site-packages/eventlet/__init__.py", line 17, in <module>
    from eventlet import convenience
  File "lib/python3.9/site-packages/eventlet/convenience.py", line 7, in <module>
    from eventlet.green import socket
  File "lib/python3.9/site-packages/eventlet/green/socket.py", line 21, in <module>
    from eventlet.support import greendns
  File "lib/python3.9/site-packages/eventlet/support/greendns.py", line 79, in <module>
    setattr(dns, pkg, import_patched('dns.' + pkg))
  File "lib/python3.9/site-packages/eventlet/support/greendns.py", line 61, in import_patched
    return patcher.import_patched(module_name, **modules)
  File "lib/python3.9/site-packages/eventlet/patcher.py", line 132, in import_patched
    return inject(
  File "lib/python3.9/site-packages/eventlet/patcher.py", line 109, in inject
    module = __import__(module_name, {}, {}, module_name.split('.')[:-1])
  File "lib/python3.9/site-packages/dns/asyncquery.py", line 40, in <module>
    from dns.query import (
  File "lib/python3.9/site-packages/dns/query.py", line 58, in <module>
    import httpx
  File "lib/python3.9/site-packages/httpx/__init__.py", line 2, in <module>
    from ._api import delete, get, head, options, patch, post, put, request, stream
  File "lib/python3.9/site-packages/httpx/_api.py", line 4, in <module>
    from ._client import Client
  File "lib/python3.9/site-packages/httpx/_client.py", line 30, in <module>
    from ._transports.default import AsyncHTTPTransport, HTTPTransport
  File "lib/python3.9/site-packages/httpx/_transports/default.py", line 30, in <module>
    import httpcore
  File "lib/python3.9/site-packages/httpcore/__init__.py", line 1, in <module>
    from ._api import request, stream
  File "lib/python3.9/site-packages/httpcore/_api.py", line 5, in <module>
    from ._sync.connection_pool import ConnectionPool
  File "lib/python3.9/site-packages/httpcore/_sync/__init__.py", line 1, in <module>
    from .connection import HTTPConnection
  File "lib/python3.9/site-packages/httpcore/_sync/connection.py", line 10, in <module>
    from .._synchronization import Lock
  File "lib/python3.9/site-packages/httpcore/_synchronization.py", line 13, in <module>
    import trio
  File "lib/python3.9/site-packages/trio/__init__.py", line 22, in <module>
    from ._core import (
  File "lib/python3.9/site-packages/trio/_core/__init__.py", line 27, in <module>
    from ._run import (
  File "lib/python3.9/site-packages/trio/_core/_run.py", line 2535, in <module>
    from ._io_epoll import EpollIOManager as TheIOManager
  File "lib/python3.9/site-packages/trio/_core/_io_epoll.py", line 188, in <module>
    class EpollIOManager:
  File "lib/python3.9/site-packages/trio/_core/_io_epoll.py", line 189, in EpollIOManager
    _epoll = attr.ib(factory=select.epoll)
AttributeError: module 'eventlet.green.select' has no attribute 'epoll'

It works if I import trio first, and then eventlet:

>>> import trio
>>> import eventlet
>>> 

Versions:

dnspython                                    2.3.0
eventlet                                     0.33.3
httpcore                                     0.17.2
httpx                                        0.24.1
trio                                         0.22.1
@mchineboy
Copy link

Responding for a bump, I ran into this today with Celery:

Module 'eventlet.green.select' has no attribute 'epoll'

Error: class uri 'eventlet' invalid or not found: 
[Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/gunicorn/util.py", line 111, in load_class
    mod = importlib.import_module('.'.join(components))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/usr/local/lib/python3.11/site-packages/gunicorn/workers/geventlet.py", line 10, in <module>
    import eventlet
  File "/usr/local/lib/python3.11/site-packages/eventlet/__init__.py", line 17, in <module>
    from eventlet import convenience
  File "/usr/local/lib/python3.11/site-packages/eventlet/convenience.py", line 7, in <module>
    from eventlet.green import socket
  File "/usr/local/lib/python3.11/site-packages/eventlet/green/socket.py", line 21, in <module>
    from eventlet.support import greendns
  File "/usr/local/lib/python3.11/site-packages/eventlet/support/greendns.py", line 79, in <module>
    setattr(dns, pkg, import_patched('dns.' + pkg))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/eventlet/support/greendns.py", line 61, in import_patched
    return patcher.import_patched(module_name, **modules)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/eventlet/patcher.py", line 132, in import_patched
    return inject(
           ^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/eventlet/patcher.py", line 109, in inject
    module = __import__(module_name, 
{}
, 
{}
, module_name.split('.')[:-1])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/dns/asyncquery.py", line 38, in <module>
    from dns.query import (
  File "/usr/local/lib/python3.11/site-packages/dns/query.py", line 63, in <module>
    import httpcore
  File "/usr/local/lib/python3.11/site-packages/httpcore/__init__.py", line 1, in <module>
    from ._api import request, stream
  File "/usr/local/lib/python3.11/site-packages/httpcore/_api.py", line 5, in <module>
    from ._sync.connection_pool import ConnectionPool
  File "/usr/local/lib/python3.11/site-packages/httpcore/_sync/__init__.py", line 1, in <module>
    from .connection import HTTPConnection
  File "/usr/local/lib/python3.11/site-packages/httpcore/_sync/connection.py", line 12, in <module>
    from .._synchronization import Lock
  File "/usr/local/lib/python3.11/site-packages/httpcore/_synchronization.py", line 13, in <module>
    import trio
  File "/usr/local/lib/python3.11/site-packages/trio/__init__.py", line 19, in <module>
    from ._core import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED  # isort: skip
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/trio/_core/__init__.py", line 21, in <module>
    from ._local import RunVar
  File "/usr/local/lib/python3.11/site-packages/trio/_core/_local.py", line 5, in <module>
    from . import _run
  File "/usr/local/lib/python3.11/site-packages/trio/_core/_run.py", line 2543, in <module>
    from ._io_epoll import EpollIOManager as TheIOManager
  File "/usr/local/lib/python3.11/site-packages/trio/_core/_io_epoll.py", line 189, in <module>
    class EpollIOManager:
  File "/usr/local/lib/python3.11/site-packages/trio/_core/_io_epoll.py", line 190, in EpollIOManager
    _epoll = attr.ib(factory=select.epoll)
                             ^^^^^^^^^^^^
AttributeError: module 'eventlet.green.select' has no attribute 'epoll'
]

Note that "trio" is buried for me in gunicorn.

@david-engelmann
Copy link

@mchineboy ran into a similar error today. any luck on a resolution?

@david-engelmann
Copy link

I was able to resolve by pinning dnspython to version 2.3.0. I opened an issue with the dnspython library - rthalley/dnspython#959

@MatYSG619
Copy link

I also had this error, I deleted the trio from the virtual environment. If you are clearly not using it, try to remove it or make a choice only in favor of one of the libraries (eventlet or trio)

eventlet==0.33.3

@kakooloukia
Copy link

kakooloukia commented Jul 19, 2023

This is Linux related:

The following commands:

pip install trio eventlet cryptography
python -c "import eventlet"

Works on windows but fails on linux

pip freeze on linux & windows are the same:

anyio==3.7.1
attrs==23.1.0
certifi==2023.5.7
cffi==1.15.1
cryptography==41.0.2
dnspython==2.4.0
eventlet==0.33.3
exceptiongroup==1.1.2
greenlet==2.0.2
h11==0.14.0
httpcore==0.17.3
idna==3.4
outcome==1.2.0
pycparser==2.21
six==1.16.0
sniffio==1.3.0
sortedcontainers==2.4.0
trio==0.22.2

Note: "trio" is used by "Selenium" while my code use "eventlet"...

@david-engelmann
Copy link

@kakooloukia you should pin dnspython==2.4.0 to 2.3.0

@kakooloukia
Copy link

@david-engelmann ,
Thank you, I already did it,
I just wanted to add more information to help resolving this issue...

@onitake
Copy link

onitake commented Jul 31, 2023

If the consequences are acceptable, the issue can be worked around by disabling greendns: https://github.com/eventlet/eventlet/blob/master/eventlet/green/socket.py#L20

import os
os.environ['EVENTLET_NO_GREENDNS'] = 'yes'
import eventlet

This will prevent importing the overridden select module that lacks epoll.

Nonetheless, this override looks like very dark magic to me. Is it really necessary to implement greendns like this?

Requiring users to downgrade dnspython to 0.23 is not a solution and will lead to serious problems when something depends on a newer version or downgrading isn't possible.

@DimStar77
Copy link

We ran into the very same error when building e.g. pgadmin4.

> python3
Python 3.11.5 (main, Aug 31 2023, 07:57:41) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from eventlet.support import greendns
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/site-packages/eventlet/__init__.py", line 17, in <module>
    from eventlet import convenience
  File "/usr/lib/python3.11/site-packages/eventlet/convenience.py", line 7, in <module>
    from eventlet.green import socket
  File "/usr/lib/python3.11/site-packages/eventlet/green/socket.py", line 21, in <module>
    from eventlet.support import greendns
  File "/usr/lib/python3.11/site-packages/eventlet/support/greendns.py", line 79, in <module>
    setattr(dns, pkg, import_patched('dns.' + pkg))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/eventlet/support/greendns.py", line 61, in import_patched
    return patcher.import_patched(module_name, **modules)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/eventlet/patcher.py", line 132, in import_patched
    return inject(
           ^^^^^^^
  File "/usr/lib/python3.11/site-packages/eventlet/patcher.py", line 109, in inject
    module = __import__(module_name, {}, {}, module_name.split('.')[:-1])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/dns/asyncquery.py", line 38, in <module>
    from dns.query import (
  File "/usr/lib/python3.11/site-packages/dns/query.py", line 63, in <module>
    import httpcore
  File "/usr/lib/python3.11/site-packages/httpcore/__init__.py", line 1, in <module>
    from ._api import request, stream
  File "/usr/lib/python3.11/site-packages/httpcore/_api.py", line 5, in <module>
    from ._sync.connection_pool import ConnectionPool
  File "/usr/lib/python3.11/site-packages/httpcore/_sync/__init__.py", line 1, in <module>
    from .connection import HTTPConnection
  File "/usr/lib/python3.11/site-packages/httpcore/_sync/connection.py", line 12, in <module>
    from .._synchronization import Lock
  File "/usr/lib/python3.11/site-packages/httpcore/_synchronization.py", line 13, in <module>
    import trio
  File "/usr/lib/python3.11/site-packages/trio/__init__.py", line 18, in <module>
    from ._core import (
  File "/usr/lib/python3.11/site-packages/trio/_core/__init__.py", line 27, in <module>
    from ._run import (
  File "/usr/lib/python3.11/site-packages/trio/_core/_run.py", line 2452, in <module>
    from ._io_epoll import EpollIOManager as TheIOManager
  File "/usr/lib/python3.11/site-packages/trio/_core/_io_epoll.py", line 188, in <module>
    class EpollIOManager:
  File "/usr/lib/python3.11/site-packages/trio/_core/_io_epoll.py", line 189, in EpollIOManager
    _epoll = attr.ib(factory=select.epoll)
                             ^^^^^^^^^^^^
AttributeError: module 'eventlet.green.select' has no attribute 'epoll'

The difference between 'working' and 'not working' could be worked out to httpcore 0.17.1 upgrade (over 0.17.0, which works)

This means we are now running into multiple variations on how to trigger the bug

@mohemiv
Copy link

mohemiv commented Nov 3, 2023

Same issue.

Using export EVENTLET_NO_GREENDNS=yes helps.

@cbf123
Copy link

cbf123 commented Dec 8, 2023

Wouldn't the "proper" fix be to add support for a monkey-patched epoll()?

@onitake
Copy link

onitake commented Dec 8, 2023

I think the proper fix would be to get rid of any code that silently overrides core Python functionality, and avoid messing up code in unrelated modules.
If eventlet must provide its implementation of select, then it should stick to using it for its own purposes.

@hatim-roker
Copy link

I am also getting similar error on Python 3.10

Traceback (most recent call last):
File "/askd/venv/bin/celery", line 8, in
sys.exit(main())
File "/askd/venv/lib/python3.10/site-packages/celery/main.py", line 13, in main
maybe_patch_concurrency()
File "/askd/venv/lib/python3.10/site-packages/celery/init.py", line 141, in maybe_patch_concurrency
patcher()
File "/askd/venv/lib/python3.10/site-packages/celery/init.py", line 102, in _patch_eventlet
import eventlet.debug
File "/askd/venv/lib/python3.10/site-packages/eventlet/init.py", line 17, in
from eventlet import convenience
File "/askd/venv/lib/python3.10/site-packages/eventlet/convenience.py", line 7, in
from eventlet.green import socket
File "/askd/venv/lib/python3.10/site-packages/eventlet/green/socket.py", line 21, in
from eventlet.support import greendns
File "/askd/venv/lib/python3.10/site-packages/eventlet/support/greendns.py", line 79, in
setattr(dns, pkg, import_patched('dns.' + pkg))
File "/askd/venv/lib/python3.10/site-packages/eventlet/support/greendns.py", line 61, in import_patched
return patcher.import_patched(module_name, **modules)
File "/askd/venv/lib/python3.10/site-packages/eventlet/patcher.py", line 132, in import_patched
return inject(
File "/askd/venv/lib/python3.10/site-packages/eventlet/patcher.py", line 109, in inject
module = import(module_name, {}, {}, module_name.split('.')[:-1])
File "/askd/venv/lib/python3.10/site-packages/dns/asyncquery.py", line 40, in
from dns.query import (
File "/askd/venv/lib/python3.10/site-packages/dns/query.py", line 58, in
import httpx
File "/askd/venv/lib/python3.10/site-packages/httpx/init.py", line 2, in
from ._api import delete, get, head, options, patch, post, put, request, stream
File "/askd/venv/lib/python3.10/site-packages/httpx/_api.py", line 4, in
from ._client import Client
File "/askd/venv/lib/python3.10/site-packages/httpx/_client.py", line 30, in
from ._transports.default import AsyncHTTPTransport, HTTPTransport
File "/askd/venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 30, in
import httpcore
File "/askd/venv/lib/python3.10/site-packages/httpcore/init.py", line 1, in
from ._api import request, stream
File "/askd/venv/lib/python3.10/site-packages/httpcore/_api.py", line 5, in
from ._sync.connection_pool import ConnectionPool
File "/askd/venv/lib/python3.10/site-packages/httpcore/_sync/init.py", line 1, in
from .connection import HTTPConnection
File "/askd/venv/lib/python3.10/site-packages/httpcore/_sync/connection.py", line 12, in
from .._synchronization import Lock
File "/askd/venv/lib/python3.10/site-packages/httpcore/_synchronization.py", line 11, in
import trio
File "/askd/venv/lib/python3.10/site-packages/trio/init.py", line 19, in
from ._core import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED # isort: skip
File "/askd/venv/lib/python3.10/site-packages/trio/_core/init.py", line 21, in
from ._local import RunVar
File "/askd/venv/lib/python3.10/site-packages/trio/_core/_local.py", line 5, in
from . import _run
File "/askd/venv/lib/python3.10/site-packages/trio/_core/_run.py", line 2543, in
from ._io_epoll import EpollIOManager as TheIOManager
File "/askd/venv/lib/python3.10/site-packages/trio/_core/_io_epoll.py", line 189, in
class EpollIOManager:
File "/askd/venv/lib/python3.10/site-packages/trio/_core/_io_epoll.py", line 190, in EpollIOManager
_epoll = attr.ib(factory=select.epoll)
AttributeError: module 'eventlet.green.select' has no attribute 'epoll'

For resolving this issue, any help is appreciated !

@ecederstrand
Copy link
Author

ecederstrand commented Apr 26, 2024

The select.epoll method from Python stdlib is deleted explicitly by the eventlet patcher. This was done to solve #169, so any solution should take that issue into account. I assume by either patching trio as well, or by properly implementing eventlet.green.select.epoll.

@4383
Copy link
Member

4383 commented Apr 26, 2024

If you are using trio or if you are in capacity of using asyncio, I'd suggest to move away from eventlet https://eventlet.readthedocs.io/en/latest/asyncio/migration.html#migration-guide

Users should get rid of monkey patching and use explicit asynchronous machisms.

We don't have the resources to properly maintain the compatibility between eventlet and all the patched modules.

@4383
Copy link
Member

4383 commented Apr 26, 2024

Eventlet is not anymore a perennial path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests