Невозможно преобразовать объект MotorCursor в список в асинхронной функции стандартным методом.
Я пытался заставить асинхронную функцию получать данные из базы данных Motor в Python и получать список данных, соответствующих поиску. Вот функция для получения данных и та, которая их печатает:
async def do_find_by_run_name(run_name):
"""
:param run_name: the name of a the run being searched for (string)
:return: MotorCursor for run found
"""
cursor = db.data_collection.find({"run_name":run_name})
loop = asyncio.get_event_loop()
return cursor
async def print_arr(cursor):
for d in await cursor.to_list(length=2):
pprint.pprint(d)
У меня есть слот PyQt, который я хочу использовать для вызова функции find_by_run_name при нажатии кнопки. Вот код для этого слота:
@pyqtSlot()
def on_find_runs_button_clicked(self):
try:
new_loop = asyncio.get_event_loop()
d = new_loop.run_until_complete(server.do_find_by_run_name("default"))
print(d)
new_loop = asyncio.get_event_loop()
v = new_loop.run_until_complete(server.print_arr(d))
except Exception as err:
try:
raise TypeError("Again !?!")
except:
pass
traceback.print_exc()
Когда я нажимаю кнопку, соответствующую этому слоту, я вижу в своем терминале следующее:
AsyncIOMotorCursor(<pymongo.cursor.Cursor object at 0x06F51EB0>)
Traceback (most recent call last):
File "C:/Users/Rohan Doshi/Documents/websockets/server\GUI.py", line 93, in on_find_runs_button_clicked
v = new_loop.run_until_complete(server.print_arr(d))
File "C:\Users\Rohan Doshi\AppData\Local\Programs\Python\Python36-32\lib\asyncio\base_events.py", line 468, in run_until_complete
return future.result()
File "C:/Users/Rohan Doshi/Documents/websockets/server\server.py", line 130, in print_arr
for d in await cursor.to_list(length=2):
RuntimeError: Task <Task pending coro=<print_arr() running at C:/Users/Rohan Doshi/Documents/websockets/server\server.py:130> cb=[_run_until_complete_cb() at C:\Users\Rohan Doshi\AppData\Local\Programs\Python\Python36-32\lib\asyncio\base_events.py:177]> got Future <Future pending> attached to a different loop
Это указывает на то, что функция do_find_by_run_name была запущена правильно, но есть проблема с запуском функции print_arr.
В попытке исправить эту проблему имя do_find_run_name было изменено на:
async def do_find_by_run_name(run_name):
"""
:param run_name: the name of a the run being searched for (string)
:return: MotorCursor for run found
"""
cursor = db.data_collection.find({"run_name":run_name})
print(cursor)
for d in await cursor.to_list(length=2):
pprint.pprint(d)
и я изменил свой слот PyQt на:
@pyqtSlot()
def on_find_runs_button_clicked(self):
try:
new_loop = asyncio.get_event_loop()
future = asyncio.run_coroutine_threadsafe(
server.do_find_by_run_name("default"),
new_loop
)
assert future.result(timeout=10)
except Exception as err:
try:
raise TypeError("Again !?!")
except:
pass
traceback.print_exc()
Когда это изменение сделано, я не вижу ничего напечатанного. Кажется, что процедура do_find_run_name никогда не выполняется.