trio
trio copied to clipboard
AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'
I'm trying to work with openai package that uses trio on Flask app hosted on Heroku.
First it failed with 'epoll issue': https://github.com/python-trio/trio/issues/2848 I tired to fix it with monkey_patch, but got a new issue:
AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'
My entry point with patch:
import eventlet
import sys
from types import ModuleType
# Apply eventlet monkey patching
eventlet.monkey_patch()
def monkey_patch_trio():
try:
import select
if not hasattr(select, 'epoll'):
class FakeEpoll:
def __init__(self, *args, **kwargs):
raise NotImplementedError("epoll is not supported on this platform")
fake_select_module = ModuleType("select")
fake_select_module.epoll = FakeEpoll
sys.modules["select"] = fake_select_module
except ImportError:
pass
monkey_patch_trio()
# Import the rest of the application after monkey patching and Flask App creating
Dependencies:
trio==0.25.1
trio-websocket==0.10.3
openai==1.30.5
eventlet==0.30.2
Error logs:
2024-06-10T13:16:50.217688+00:00 app[web.1]: Traceback (most recent call last):
2024-06-10T13:16:50.217689+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 2190, in wsgi_app
2024-06-10T13:16:50.217689+00:00 app[web.1]: response = self.full_dispatch_request()
2024-06-10T13:16:50.217690+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 1486, in full_dispatch_request
2024-06-10T13:16:50.217690+00:00 app[web.1]: rv = self.handle_user_exception(e)
2024-06-10T13:16:50.217691+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask_cors/extension.py", line 176, in wrapped_function
2024-06-10T13:16:50.217691+00:00 app[web.1]: return cors_after_request(app.make_response(f(*args, **kwargs)))
2024-06-10T13:16:50.217691+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 1484, in full_dispatch_request
2024-06-10T13:16:50.217692+00:00 app[web.1]: rv = self.dispatch_request()
2024-06-10T13:16:50.217692+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask/app.py", line 1469, in dispatch_request
2024-06-10T13:16:50.217693+00:00 app[web.1]: return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
2024-06-10T13:16:50.217693+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/flask_login/utils.py", line 290, in decorated_view
2024-06-10T13:16:50.217693+00:00 app[web.1]: return current_app.ensure_sync(func)(*args, **kwargs)
2024-06-10T13:16:50.217694+00:00 app[web.1]: File "/app/app/main/routes/calls_recognition.py", line 14, in add_calls_to_queue
2024-06-10T13:16:50.217695+00:00 app[web.1]: CallsRecognitionManager(branch='sm').add_calls_from_amo(_filter={'contact_id': request.args.get('contact_id')})
2024-06-10T13:16:50.217695+00:00 app[web.1]: File "/app/app/calls_recognition/manager.py", line 24, in __init__
2024-06-10T13:16:50.217695+00:00 app[web.1]: self.calls_data_client = CallsDataClient(schema=branch)
2024-06-10T13:16:50.217695+00:00 app[web.1]: File "/app/app/calls_recognition/data_client.py", line 45, in __init__
2024-06-10T13:16:50.217695+00:00 app[web.1]: self.gpt_processor = GPTProcessor()
2024-06-10T13:16:50.217695+00:00 app[web.1]: File "/app/app/calls_recognition/gpt_processor.py", line 11, in __init__
Here starts the problem:
2024-06-10T13:16:50.217696+00:00 app[web.1]: from openai import OpenAI
2024-06-10T13:16:50.217696+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/openai/__init__.py", line 8, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]: from . import types
2024-06-10T13:16:50.217697+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/openai/types/__init__.py", line 5, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]: from .batch import Batch as Batch
2024-06-10T13:16:50.217697+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/openai/types/batch.py", line 7, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]: from .._models import BaseModel
2024-06-10T13:16:50.217697+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/openai/_models.py", line 24, in <module>
2024-06-10T13:16:50.217697+00:00 app[web.1]: from ._types import (
2024-06-10T13:16:50.217698+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/openai/_types.py", line 21, in <module>
2024-06-10T13:16:50.217698+00:00 app[web.1]: import httpx
2024-06-10T13:16:50.217698+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpx/__init__.py", line 2, in <module>
2024-06-10T13:16:50.217698+00:00 app[web.1]: from ._api import delete, get, head, options, patch, post, put, request, stream
2024-06-10T13:16:50.217698+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpx/_api.py", line 4, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]: from ._client import Client
2024-06-10T13:16:50.217699+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpx/_client.py", line 30, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]: from ._transports.default import AsyncHTTPTransport, HTTPTransport
2024-06-10T13:16:50.217699+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpx/_transports/default.py", line 30, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]: import httpcore
2024-06-10T13:16:50.217699+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/__init__.py", line 1, in <module>
2024-06-10T13:16:50.217699+00:00 app[web.1]: from ._api import request, stream
2024-06-10T13:16:50.217700+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_api.py", line 5, in <module>
2024-06-10T13:16:50.217700+00:00 app[web.1]: from ._sync.connection_pool import ConnectionPool
2024-06-10T13:16:50.217700+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_sync/__init__.py", line 1, in <module>
2024-06-10T13:16:50.217700+00:00 app[web.1]: from .connection import HTTPConnection
2024-06-10T13:16:50.217700+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_sync/connection.py", line 12, in <module>
2024-06-10T13:16:50.217700+00:00 app[web.1]: from .._synchronization import Lock
2024-06-10T13:16:50.217701+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/httpcore/_synchronization.py", line 13, in <module>
2024-06-10T13:16:50.217701+00:00 app[web.1]: import trio
2024-06-10T13:16:50.217701+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/trio/__init__.py", line 26, in <module>
2024-06-10T13:16:50.217701+00:00 app[web.1]: from . import abc, from_thread, lowlevel, socket, to_thread
2024-06-10T13:16:50.217702+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/trio/socket.py", line 16, in <module>
2024-06-10T13:16:50.217702+00:00 app[web.1]: from . import _socket
2024-06-10T13:16:50.217702+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/trio/_socket.py", line 526, in <module>
2024-06-10T13:16:50.217702+00:00 app[web.1]: class SocketType:
2024-06-10T13:16:50.217702+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/trio/_socket.py", line 719, in SocketType
2024-06-10T13:16:50.217705+00:00 app[web.1]: @_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
2024-06-10T13:16:50.217705+00:00 app[web.1]: AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'
As a quick fix you can probably import trio before monkey patching. This will cache trio with un-patched system things.
There has to be a way to fix this that isn't just a game of whack-a-mole but I don't have any ideas.
If I import trio before monkey patching it will fall with "AttributeError: module 'select' has no attribute 'epoll'".
I ended up with this to avoid both attribute errors:
def monkey_patch_trio():
try:
import select
if not hasattr(select, 'epoll'):
class FakeEpoll:
def __init__(self, *args, **kwargs):
raise NotImplementedError("epoll is not supported on this platform")
fake_select_module = ModuleType("select")
fake_select_module.epoll = FakeEpoll
sys.modules["select"] = fake_select_module
# Patch GreenSocket before trio._socket is imported
from eventlet.greenio.base import GreenSocket as EventletGreenSocket
if not hasattr(EventletGreenSocket, 'sendmsg'):
setattr(EventletGreenSocket, 'sendmsg', lambda *args, **kwargs: None)
if not hasattr(EventletGreenSocket, 'recvmsg'):
setattr(EventletGreenSocket, 'recvmsg', lambda *args, **kwargs: None)
if not hasattr(EventletGreenSocket, 'recvmsg_into'):
setattr(EventletGreenSocket, 'recvmsg_into', lambda *args, **kwargs: None)
# Now import trio._socket
import trio._socket as trio_socket
import socket as _stdlib_socket
from functools import wraps as _wraps
class PatchedSocketType(trio_socket.SocketType):
@_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
def sendmsg(self, *args, **kwargs):
raise NotImplementedError("sendmsg is not supported on this platform")
@_wraps(_stdlib_socket.socket.recvmsg, assigned=(), updated=())
def recvmsg(self, *args, **kwargs):
raise NotImplementedError("recvmsg is not supported on this platform")
@_wraps(_stdlib_socket.socket.recvmsg_into, assigned=(), updated=())
def recvmsg_into(self, *args, **kwargs):
raise NotImplementedError("recvmsg_into is not supported on this platform")
trio_socket.SocketType = PatchedSocketType
except ImportError:
pass
Sorry, I mean import trio before running eventlet.monkey_patch().
Ok I thought about this some more and this is totally just an eventlet bug. They claim GreenSocket is "100% api compatible with socket.socket":
https://github.com/eventlet/eventlet/blob/8bac9b2bb5ba02d42305446327a117ff51af177b/eventlet/greenio/base.py#L119-L122
Hi, ich sehe, dass der Post zwar schon ein wenig her ist, aber ich habe soeben mit Darkgpt das selbe Problem gehabt. Und zwar hatte ich folgende Fehlermeldung.
Ich habe aber auch die Lösung,oder eine Lösung. Führt Darkgpt, in einer Virtuellen Python Umgebung aus, dann funktioniert es. Bei mir zumindest.
File "/home/.local/lib/python3.12/site-packages/trio/__init__.py", line 26, in <module>
from . import abc, from_thread, lowlevel, socket, to_thread
File "/home/.local/lib/python3.12/site-packages/trio/socket.py", line 16, in <module>
from . import _socket
File "/home/.local/lib/python3.12/site-packages/trio/_socket.py", line 526, in <module>
class SocketType:
File "/home/.local/lib/python3.12/site-packages/trio/_socket.py", line 719, in SocketType
@_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'
Added import trio to the top of eventlet/patcher.py and this resolved AttributeError: type object 'GreenSocket' has no attribute 'sendmsg' in mutltiple python apps.
This bug is really weird. I don't know what triggers it exactly, but I've just stumbled upon it in manhole (https://github.com/ionelmc/python-manhole/issues/70), which tries really hard to figure out the original socket, and essentially imports eventlet just for that. The workaround there is to just ignore this exception altogether and move on (https://github.com/ionelmc/python-manhole/pull/71).
We've also seen this in unrelated packages in Debian, first filed against cumin and thought to be related to openstack, but now i'm thinking it's a broader, eventlet related problem: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1093157
What I've concluded is that this is a fundamental problem with how eventlet monkeypatches things and that there isn't really anything Trio can do on its end to solve it, and eventlet itself says not to use it for new projects and for all intents and purposes can be considered archived. Best solution I've seen so far is to import trio before anything else so that by the time eventlet tries to monkeypatch sockets trio has already completed what it needs to to initialize properly. Trio and eventlet are two very different async frameworks and things won't work between the two anyways, this is only a solution for on-import errors.