Я пишу сценарий, который использует API Graph для Microsoft для подключения и запроса пользовательских данных из Entra ID в Azure. У меня есть две разные функции, которые я пытаюсь использовать: одна, которая получает пользователей из указанной группы, и другая, которая извлекает отображаемое имя пользователя по значению его идентификатора. Если я использую asyncio.run() для запуска того или другого, оба будут работать без проблем. Но если я попытаюсь включить в свой скрипт оба одновременно, то получу ошибку на втором. Я все еще изучаю тонкости асинхронного программирования, поэтому не могу хоть убей понять, почему я не могу заставить работать второй вызов asyncio.run().
У меня есть этот код в моем основном скрипте, который выполняет функцию в другом скрипте:
async def get_all_group_members():
memberListAll = []
for group in groupList:
# print(f"We are trying to run group {group}")
results = await gq.get_group_user(group['GroupID'], graphServiceClient)
memberDict = {"GroupName":group["GroupName"], "GroupID":group["GroupID"], "MemberList":results}
memberListAll.append(memberDict)
return memberListAll
results = asyncio.run(get_all_group_members())
Определение get_group_user:
memberList = []
members = await graphServiceClient.groups.by_group_id(groupID).members.get()
if members and members.value:
for member in members.value:
user = await graphServiceClient.users.by_user_id(member.id).get()
if user:
memberList.append(user.display_name)
return memberList
Затем в моем основном сценарии у меня есть вторая функция, которая ссылается на другую функцию из второго файла сценария:
async def get_user_name():
results = await gq.get_user_by_id(member=member,graphServiceClient=graphServiceClient)
return results
results2 = asyncio.run(get_user_name())
Определение get_user_by_id:
user = await graphServiceClient.users.by_user_id(member).get()
print(user)
Если я закомментирую все для второй функции, get_group_user
, первая функция будет работать нормально. Если я закомментирую все для первой функции, get_all_group_members
, вторая функция будет работать нормально. Просто когда я действительно запускаю оба, второй выходит из строя, и я не знаю, почему, поэтому не могу понять, как это исправить.
Почему я не могу вызвать asyncio.run() в сценарии более одного раза? Как мне изменить свой сценарий, чтобы я мог успешно запускать обе эти функции асинхронно и получать нужные мне данные?
честно говоря, я думаю, что все уроки показывают, что вам нужно объединить все функции в одну функцию и запускать ее с помощью одной run()
. И я думаю, что run()
был создан для запуска программы от начала до конца - без выхода и запуска другой run()
Если вы разобрались сами, то можете сами ответить на свой вопрос и отметить его как принятый! Таким образом, вопрос не остается открытым.
@jupiterbjy Я не смог ответить на свой вопрос, когда сам нашел решение, но вижу, что теперь я могу добавить ответ, так что сделаю это.
В документации asyncio.run указано, что его следует вызывать один раз для программы.
Эту функцию следует использовать в качестве основной точки входа для асинхронных программ, и в идеале ее следует вызывать только один раз.
Чтобы запускать что-то одновременно, вам нужно создать Task
для каждой асинхронной функции. Это будет чередовать выполнение двух методов.
async def main():
await asyncio.gather(get_all_group_members(), get_user_name())
if __name__ == '__main__':
asyncio.run(main())
Но если одна асинхронная функция должна завершиться раньше любой другой, то ваше самостоятельно найденное решение правильное: запускает их последовательно.
await method_1()
await method_2()
...
Вот решение, которое в конечном итоге сработало после того, как я прошел через больше проб и ошибок со своей проблемой.
Чтобы иметь возможность запускать обе асинхронные функции, я создал еще одну асинхронную функцию, в которую поместил обе другие функции, а затем вызвал эту функцию с помощью asyncio.run(). Я до сих пор не знаю, почему я не могу вызвать asyncio.run() два раза в одном и том же сценарии, не вызывая при этом проблем, но, по крайней мере, я могу двигаться вперед с этой проблемой, которую пытаюсь решить. Вот как код выглядит сейчас:
async def get_all_group_members():
memberListAll = []
for group in groupList:
# print(f"We are trying to run group {group}")
results = await gq.get_group_user(group['GroupID'], graphServiceClient)
memberDict = {"GroupName":group["GroupName"], "GroupID":group["GroupID"], "MemberList":results}
memberListAll.append(memberDict)
return memberListAll
async def get_user_name():
member = '<id value>'
results = await gq.get_user_by_id(member=member,graphServiceClient=graphServiceClient)
return results
async def run_async_functions():
groupResults = await get_all_group_members()
usernameResults = await get_user_name()
return groupResults, usernameResults
groupResults, usernameResults = asyncio.run(run_async_functions())
После загрузки результатов обеих функций в groupResults
и usernameResults
я могу распечатать значения, а это значит, что я смогу взаимодействовать с ними так, как мне нужно для продвижения вперед.
Пожалуйста, всегда публикуйте сообщение об ошибке. Я не могу воспроизвести «что-то не работает». Как правило,
asyncio.run(...)
можно запустить дважды, если он выполняется последовательно, а не вложенно. Если вы столкнулись с чем-то вродеcannot create event loop if there is already an event loop running
, вы, вероятно, выполнили одноasyncio.run(...)
внутри другого. Это не работает.