R
R
r1dddy4sv2021-12-17 18:09:58
Python
r1dddy4sv, 2021-12-17 18:09:58

How to use asyncio inside Thread Python?

I have a pyqt5 application, inside the function of which I create threads through a modified class, in order to stop the thread at the request of the user. After that, asyncio is used inside the thread, which causes a conflict.

results=[]
def get_tasks(session):
    tasks = []
    
    for i in range(0,requestsNumber):
        tasks.append(asyncio.create_task(session.post(url, data = json.dumps(js), ssl=False)))
    return tasks

async def get_symbols(headers):
    async with aiohttp.ClientSession(headers=headers) as session:
        tasks = get_tasks(session)
        responses = await asyncio.gather(*tasks)
        for response in responses:
            results.append(await response.text())

def startSsc(headers):
    asyncio.get_event_loop().run_until_complete(get_symbols(headers))


class thread_with_exception(threading.Thread):
    def __init__(self,name):
        threading.Thread.__init__(self)
        self.name = name
        
   def run(self):
        #some code (основная функция для запуска в многопоточности)
        startSsc(head)

    def get_id(self):
 
        # returns id of the respective thread
        if hasattr(self, '_thread_id'):
            return self._thread_id
        for id, thread in threading._active.items():
            if thread is self:
                return id
  
    def raise_exception(self):
        thread_id = self.get_id()
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,
              ctypes.py_object(SystemExit))
        if res > 1:
            ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
            print('Exception raise failure')

class Ui_Dialog(object):
    def setupUi(self,code,end, Dialog):
        #some code

    def start(self):
         s = thread_with_exception(some_args)
         s.start()
         self.ap[i]=s

    def stop_all_tasks(self):
         for i in self.ap:
              self.ap[i].raise_exception()
              self.ap[i].join()
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QDialog()
    ui = Ui_Dialog()
    ui.setupUi(code,end,MainWindow)
    MainWindow.show()        
    sys.exit(app.exec_())

and inside the function to run in multithreading, you need to use functions using asyncio, which causes a conflict

error:
RuntimeError("There is no current event loop in thread '0'.")

I solve it with the following changes:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

then the following problem occurs intermittently:
ClientOSError(22, 'Указанное сетевое имя более недоступно', None, 64, None)


Is there a way to customize my code?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vindicar, 2021-12-18
@r1dddy4sv

First, several asynchronous tasks coexist perfectly with each other. Why do you even need threads for this? What's wrong with loop.create_task(), or asyncio.gather()?
Secondly, it is much easier to wrap a long synchronous code into a thread, and already a thread into an asynchronous task, than vice versa. Think about it.
Thirdly, technically you can create your own reactor loop (asyncio loop) in each thread. Read the asyncio docs on how to do this. But you need to remember that async objects from different reactors are not friendly with each other. So I emphasize in red: do not do this . It is better to first try to approach the problem in a different way.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question