简体   繁体   English

在 Gtk 主循环中运行的 Asyncio 调用

[英]Asyncio calls running in Gtk main loop

Okey guys question concerning asyncio and Gtk+.好吧,关于 asyncio 和 Gtk+ 的问题。 How can I run code below in Gtk.main loop ?如何在 Gtk.main 循环中运行下面的代码? I searched for example but couldn't find any.例如,我进行了搜索,但找不到任何内容。

#!/usr/bin/python3.4

import asyncio

@asyncio.coroutine
def client_connected_handler(client_reader, client_writer):
    print("Connection received!")
    client_writer.write(b'Hello')
    while True:
        data = yield from client_reader.read(8192)
        if not data:
            break
        if 'EXIT' in data.decode():
            print("Closing server")
            break   
        print(data)
        client_writer.write(data)
    print('Server is closed')


loop = asyncio.get_event_loop()
Server=asyncio.start_server(client_connected_handler, 'localhost', 2222)
server=loop.run_until_complete(Server)
loop.run_forever()

EDIT:编辑:

Okey I should write my experiance with gbulb.好吧,我应该写下我对 gbulb 的体验。 First I searched it using pip3 .首先我使用 pip3 搜索它。 I found it and tried to install it but it failed(I was using super user for installation) due bad links.我找到了它并尝试安装它但由于链接错误而失败(我使用超级用户进行安装)。 Next I downloaded it from their repository and installed it .I got this example I run it and got some errors for missing arguments in their core module.I don't know really which error is it cause Iam writing this from different PC I'll update is ASAP.接下来,我从他们的存储库下载并安装了它。我得到了这个例子,我运行它并在他们的核心模块中丢失了一些参数。我真的不知道是哪个错误导致我从不同的 PC 写这个我会更新是尽快。 Also I would be grateful if anybody else could test it.另外,如果有人可以测试它,我将不胜感激。

As of 2020, the gbulb library appears to be unmaintained .截至 2020 年,gbulb 库似乎无人维护 Anyone wishing to integrate asyncio and GTK should only consider the second part of the answer (showing asyncio running in a dedicated thread) or take a look at asyncio-glib , which integrates asyncio and GTK using an approach more minimalistic and robust than that taken by gbulb.任何希望集成 asyncio 和 GTK 的人都应该只考虑答案的第二部分(显示 asyncio 在专用线程中运行)或查看asyncio-glib ,它使用比所采用的方法更简约和健壮的方法集成 asyncio 和 GTK灯泡。

Original answer follows below.原答案如下。


The gbulb library is designed to provide a connector between the asyncio event loop as specified by PEP 3156 and the GLib main loop implementation. gbulb旨在提供 PEP 3156 指定的 asyncio 事件循环和 GLib 主循环实现之间的连接器。 However, the current master of gbulb is broken for asyncio as shipped with Python 3.4.但是,在 Python 3.4 附带的gbulb ,当前的gbulb大师gbulb被破坏。 To fix this, you can check out this fork instead of the master.要解决此问题,您可以查看此 fork而不是 master。 (The problem was later fixed upstream.) (问题后来在上游得到解决。)

With a working gbulb, it is trivial to modify your example to both accept incoming connections and run GTK:使用工作 gbulb,修改您的示例以接受传入连接并运行 GTK 是微不足道的:

#!/usr/bin/python3

import asyncio, gbulb
from gi.repository import Gtk
asyncio.set_event_loop_policy(gbulb.GLibEventLoopPolicy())

@asyncio.coroutine
def client_connected_handler(client_reader, client_writer):
    print("Connection received!")
    client_writer.write(b'Hello')
    while True:
        data = yield from client_reader.read(8192)
        if not data:
            break
        if 'EXIT' in data.decode():
            print("Closing server")
            break   
        print(data)
        client_writer.write(data)
    print('Server is closed')

loop = asyncio.get_event_loop()
loop.run_until_complete(
    asyncio.start_server(client_connected_handler, 'localhost', 2222))

w = Gtk.Window()
w.add(Gtk.Label('hey!'))
w.connect('destroy', Gtk.main_quit)
w.show_all()

loop.run_forever()

Another possibility is to run the asyncio event loop in a different thread:另一种可能性是在不同的线程中运行 asyncio 事件循环:

#!/usr/bin/python3

import asyncio, threading
from gi.repository import Gtk

async def client_connected_handler(client_reader, client_writer):
    # ... unchanged ...

def run_asyncio():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(
        asyncio.start_server(client_connected_handler, 'localhost', 2222))
    loop.run_forever()

threading.Thread(target=run_asyncio).start()

w = Gtk.Window()
w.add(Gtk.Label('hey!'))
w.connect('destroy', Gtk.main_quit)
w.show_all()

Gtk.main()

This has the advantage of not requiring gbulb at all (it is not clear how well gbulb has been tested in production).这样做的好处是根本不需要gbulb (目前尚不清楚gbulb在生产中的测试情况)。 One does need to be careful, however, to use thread-safe functions to communicate between the GUI (main) thread and the asyncio thread.但是,使用线程安全函数在 GUI(主)线程和 asyncio 线程之间进行通信确实需要小心。 This means using loop.call_soon_threadsafe or asyncio.run_coroutine_threadsafe to submit things to asyncio from GTK, and GLib.idle_add to submit things to GTK from asyncio.这意味着使用loop.call_soon_threadsafeasyncio.run_coroutine_threadsafe从 GTK 向 asyncio 提交事物,使用 GLib.idle_add 从GLib.idle_add向 GTK 提交事物。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM