Асинхронный питон с угрем
Я создаю настольное приложение с использованием угря. Однако у меня возникла проблема с одновременным запуском функций.
Идея угря заключается в том, что он позволяет электрону общаться с Python через JS. Итак, я создал кнопку в пользовательском интерфейсе eel, которая запускает часть моей программы (несколько асинхронных сеансов aiohttp). Функция, которая их запускает, определяется как асинхронная, т.е. async def main():
, И все функции, выполняемые main()
также асинхронны. Вот общий план программы:
import eel
import asyncio
from aiohttp import ClientSession
options = {
'mode': 'custom',
'args': ['node_modules/electron/dist/electron.exe', '.'],
}
@eel.expose
async def start_program(): # this is run when the user clicks the run button
await main()
@eel.expose
async def test_print(): # this is run when the user clicks the test button
print("test")
async def main():
tasks = []
loop = asyncio.get_event_loop()
for i in range(instances):
task = asyncio.ensure_future(launch(url))
tasks.append(task)
loop.run_until_complete(asyncio.wait(tasks))
async def launch(url):
done = False
async with ClientSession() as session:
while not done:
async with session.get(url, timeout=40) as initial:
html_text = await initial.text()
if x in html_text:
done = True
await session.close()
if __name__ == "__main__":
eel.init('web')
eel.start('html/index.html', options=options)
И тогда в моем JavaScript у меня есть:
async function start_program_js() { // this is run when the user clicks the run button
await eel.start_program()();
}
async function test_print_js() { // this is run when the user clicks the test button
await eel.test_print()();
}
Таким образом, желаемый результат заключается в том, что после того, как я уже нажал кнопку "Выполнить", если я затем нажму кнопку "Проверить", будет напечатано "Проверка". Однако на данный момент ни один из них не работает. Я мог бы "запустить" на работу, изменив async def main():
в def main():
, async def start_program():
в def start_program():
а также async def test_print():
в def test_print():
, Затем в JS я изменил его на
function start_program_js() { // this is run when the user clicks the run button
eel.start_program();
}
function test_print_js() { // this is run when the user clicks the test button
eel.test_print();
}
Тем не менее, теперь моя проблема в том, что кнопка "тест" не будет ничего делать, если я уже нажал "запустить". Он работает сам по себе, но не в том случае, если запущен "запуск".
Я думал, что асинхронный подход, который я подробно описал вначале, сработает, но использование этого и нажатие кнопки "выполнить" вызвало эту ошибку:
Traceback (most recent call last):
File "src\gevent\greenlet.py", line 766, in gevent._greenlet.Greenlet.run
File "C:\Users\x\AppData\Local\Programs\Python\Python37-32\lib\site-packages\eel\__init__.py", line 209, in _process_message
'value': return_val }))
File "C:\Users\x\AppData\Local\Programs\Python\Python37-32\lib\json\__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "C:\Users\x\AppData\Local\Programs\Python\Python37-32\lib\json\encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "C:\Users\x\AppData\Local\Programs\Python\Python37-32\lib\json\encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "C:\Users\x\AppData\Local\Programs\Python\Python37-32\lib\json\encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type coroutine is not JSON serializable
2019-06-03T13:00:59Z <Greenlet at 0x4f4b4b0: _process_message({'call': 6.074835210306471, 'name': 'start_program', 'ar, <geventwebsocket.websocket.WebSocket object at 0x0)> failed with TypeError
C:\Users\x\AppData\Local\Programs\Python\Python37-32\lib\site-packages\gevent\libuv\loop.py:193: RuntimeWarning: coroutine 'start_program' was never awaited
super(loop, self)._run_callbacks()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Кто-нибудь знает, как я могу решить эту проблему?
Благодарю.
РЕДАКТИРОВАТЬ: я только что заметил, что есть асинхронный раздел в readme. Я пытался повторить это, но я не могу заставить его работать. Я пытался
@eel.expose
def start_program(): # this is run when the user clicks the run button
eel.spawn(main)
@eel.expose
def test_print(): # this is run when the user clicks the test button
eel.spawn(test_print_x)
def test_print_x():
print("test")
Тем не менее, у меня та же проблема, что и раньше, то есть не работает функция кнопки "тест".