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

Error with send_json Function in AsyncJsonWebsocketConsumer #2100

Closed
gaurav-jo1 opened this issue May 18, 2024 · 6 comments
Closed

Error with send_json Function in AsyncJsonWebsocketConsumer #2100

gaurav-jo1 opened this issue May 18, 2024 · 6 comments

Comments

@gaurav-jo1
Copy link

Environment Details:
Operating System: Ubuntu 24.04 LTS
Browser: Google Chrome
Django version: 5.0.4
Channels version: 4.1.0

pip freeze output:

asgiref==3.8.1 asyncpg==0.29.0 attrs==23.2.0 autobahn==23.6.2 Automat==22.10.0 cffi==1.16.0 channels==4.1.0 channels-redis==4.2.0 constantly==23.10.4 cryptography==42.0.5 daphne==4.1.2 Django==5.0.4 django-cors-headers==4.3.1 django-redis==5.4.0 djangorestframework==3.15.1 djangorestframework-simplejwt==5.3.1 hyperlink==21.0.0 idna==3.7 incremental==22.10.0 msgpack==1.0.8 psycopg2-binary==2.9.9 pyasn1==0.6.0 pyasn1_modules==0.4.0 pycparser==2.22 PyJWT==2.8.0 pyOpenSSL==24.1.0 python-dotenv==1.0.1 redis==5.0.3 service-identity==24.1.0 setuptools==69.5.1 six==1.16.0 sqlparse==0.5.0 Twisted==24.3.0 txaio==23.1.1 typing_extensions==4.11.0 whitenoise==6.6.0 zope.interface==6.3


Expected Behavior:

I anticipated that upon establishing a connection using AsyncJsonWebsocketConsumer, a "welcome message" would be successfully sent to the client side, similar to the behavior observed with JsonWebsocketConsumer.

Expected Behavior Code using JsonWebsocketConsumer:

Screenshot from 2024-05-18 11-48-54

Expected Response:

Screenshot from 2024-05-18 11-47-41

Actual Behavior:

I anticipated that upon establishing a connection using AsyncJsonWebsocketConsumer, a "welcome message" would be successfully sent to the client side, similar to the behavior observed with JsonWebsocketConsumer.

Actual Behavior Code:

Screenshot from 2024-05-18 12-06-29

Error Encountered:
The error encountered is as follows:

Screenshot from 2024-05-18 11-54-27


  • I am using the command daphne to start the ASGI development server. Upon execution, the server starts successfully and listens for incoming connections at http://127.0.0.1:8000/.
@gaurav-jo1
Copy link
Author

After examining the code within the parent class (AsyncJsonWebsocketConsumer), I noticed that the encoding process for the content using json.dumps(content) was utilizing the await keyword. However, I found that removing the await and simply using json.dumps resolved the error. This adjustment allowed the "welcome message" to be sent successfully to the client side without encountering any error.

@carltongibson
Copy link
Member

carltongibson commented May 18, 2024

The encode_json method is unchanged since it was introduced:

de82aaa#diff-8adaf2e6e01ec2cc05dd10bfd212d6dddfadabe0ddc679b821e03024806647b7R254-R256

    @classmethod
     async def encode_json(cls, content):
         return json.dumps(content)

@gaurav-jo1
Copy link
Author

encode_json is defined as an async function, but it uses json.dumps which is a synchronous function.

Error explanation:

When we call await self.encode_json(content), it treats the return value of json.dumps(content) as a coroutine, but since json.dumps returns a string synchronously, it raises the TypeError.

Here is the error message:

Screenshot from 2024-05-18 16-07-39

If I am misunderstanding something, please let me know.

@carltongibson
Copy link
Member

It looks like you've overridden a method maybe and forgotten an async.

Please post code rather than screenshots.

The async send_json method is covered by the test suite. If you could add a test demonstrating your issue, that would help to identify what you're seeing.

@gaurav-jo1
Copy link
Author

chats/consumers.py

class ChatConsumer(AsyncJsonWebsocketConsumer):
    async def connect(self):
        # Accept the connection
        await self.accept()

        # Send a welcome message
        await self.send_json(
            {
                "type": "welcome_message",
                "message": "Welcome to the Websocket Connection",
            }
        )

The error traceback is as follows:

python3.12/site-packages/channels/generic/websocket.py", line 282, in send_json
    await super().send(text_data=await self.encode_json(content), close=close)
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: object str can't be used in 'await' expression

The full chats/consumers.py file can be found here: ChatConsumer file.

Here is a video demo of the error.

Screencast.from.2024-05-20.17-22-47.webm

@carltongibson
Copy link
Member

Compare your class:

https://github.com/DevGauravJoshi/python_async/blob/eb0cfb1894fcaaa1aaeed245a032ff1c6ecd40c3/backend/chats/consumers.py#L180-L182

to the base class:

@classmethod
async def encode_json(cls, content):
return json.dumps(content)

By overriding this method without using the async keyword, the await call at the error point is receiving a string, rather than a coroutine object. You want to pass UUIDEncoder, but you still need to declare the method async def.

@carltongibson carltongibson closed this as not planned Won't fix, can't repro, duplicate, stale May 20, 2024
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

2 participants