question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot instantiate async_to_sync inside a SyncConsumer method

See original GitHub issue

I’m getting this error from the worker (BTBitstampTrades). Any clue?

I think is because I’m defining the callback function inside the Worker method.

How could I send something to the channel layer from inside the callback def?

error from callback <bound method Connection._on_message of <Connection(Thread-1, started daemon 140206694061824)>>: You cannot instantiate AsyncToSync inside a thread that wasn’t made using SyncToAsync

My code:

class WsTradeHistory(JsonWebsocketConsumer):
    def connect(self):
        self.accept()
        async_to_sync(self.channel_layer.group_add)("users", self.channel_name)
        print('USUARIO CONECTADO' + self.channel_name)

    def disconnect(self, code):
        async_to_sync(self.channel_layer.group_discard)("users", self.channel_name)

    def receive_json(self, content, **kwargs):
        if content['group_request']:
            group_req = content['group_request']
            async_to_sync(self.channel_layer.group_add)(group_req, self.channel_name)
            if group_req == 'th_bitstamp_BTC_USD':
                print('BITSTAMP TRADES!')
                # self.bitstamp_trades('')
                async_to_sync(self.channel_layer.send)(
                    "bitstamp_trades",
                    {
                        "type": "get.data",
                    }
                )

    def trade_data(self, event):
        print('Enviando trade data al Usuario')
        self.send_json(json.loads(event["text"]))

    def one_trade(self, event):
        self.send_json(json.loads(event["text"]))

class BTBitstampTrades(SyncConsumer):

    def get_data(self, event):
        print('START WORKER')

        def callback(*args, **kwargs):
            async_to_sync(self.channel_layer.send)(
                "th_bitstamp_BTC_USD",
                {
                    "type": "one.trade",
                    "text": args[0]
                }
            )

        # We can't subscribe until we've connected, so we use a callback handler
        # to subscribe when able
        def connect_handler(data):
            channel = pusher.subscribe('live_trades')
            channel.bind('trade', callback)

        pusher = pysher.Pusher('de504dc5763aeef9ff52')
        pusher.connection.bind('pusher:connection_established', connect_handler)
        pusher.connect()

Ubuntu 16.04, Google Chrome, Django y Channels 2.02, Python 3.6

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
andrewgodwincommented, Feb 23, 2018

I just advise that you upgrade packages you’re finding issues in before reporting an issue. It’s a bit confusing for Channels as we have four - asgiref, daphne, channels and channels_redis.

1reaction
hishnashcommented, Feb 23, 2018

No, i don think it is to do with it being inside a nested def but rather that callback is called by pysher.Pusher and that is happing after def get_data(self, event): has completed (your get_data method is automaticly wrapped in a SyncToAsync)

try:

def callback(*args, **kwargs):
    if getattr(SyncToAsync.threadlocal, "main_event_loop", None) is None:
        loop = asyncio.get_event_loop()
        loop.run_until_complete(
            self.channel_layer.send(
                "th_bitstamp_BTC_USD",
                {
                    "type": "one.trade",
                    "text": args[0]
                }
            )
        )
        loop.close()
    else:
        async_to_sync(self.channel_layer.send)(
            "th_bitstamp_BTC_USD",
            {
                "type": "one.trade",
                "text": args[0]
            }
        )
Read more comments on GitHub >

github_iconTop Results From Across the Web

Cannot call AsyncToSync twice in one sync context ... - GitHub
I am using a SyncConsumer which adds itself to a group on websocket.connect with group_add method of channel_layer. class ...
Read more >
Django Channels Error: you cannot use AsyncToSync in the ...
Exception inside application: You cannot use AsyncToSync in the same thread as an async event loop - just await the async function directly....
Read more >
Consumers — Channels 4.0.0 documentation
A consumer is a subclass of either channels.consumer.AsyncConsumer ; Let's look at a basic example of a SyncConsumer ; Consumers are structured around...
Read more >
Channels Documentation - Read the Docs
Channels is a project that takes Django and extends its abilities beyond HTTP - to handle WebSockets, chat protocols,.
Read more >
Channels SyncConsumer base_send issue? - Django Forum
Channels 3.0.4 / Django 4.0.2 I'm using runworker to run a combination of sync and async background worker processes in one process.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found