Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:执行HTTP请求时不阻塞GTK UI的正确方法_Python_Gtk_Python Requests_Gtk3_Grequests - Fatal编程技术网

Python:执行HTTP请求时不阻塞GTK UI的正确方法

Python:执行HTTP请求时不阻塞GTK UI的正确方法,python,gtk,python-requests,gtk3,grequests,Python,Gtk,Python Requests,Gtk3,Grequests,问:在从远程HTTP源加载数据时,不阻止GTK UI的正确方法是什么 背景: 我正在做一件事。我修改了原始项目,使其可以同时运行多个ticker 示意图上,它的工作原理如下: 主线程找到要加载的每个ticker,并为每个ticker启动一个GTK libAppindicator实例(Indicator)。然后,每个指示器加载一个类,该类从远程API检索股票代码数据并将其反馈给指示器 然而,我注意到UI在不规则的时间间隔内变得不负责任。我假设这是因为HTTP请求(带有请求库)被阻塞。所以我决定在自

问:在从远程HTTP源加载数据时,不阻止GTK UI的正确方法是什么

背景:

我正在做一件事。我修改了原始项目,使其可以同时运行多个ticker

示意图上,它的工作原理如下:

主线程找到要加载的每个ticker,并为每个ticker启动一个GTK libAppindicator实例(Indicator)。然后,每个指示器加载一个类,该类从远程API检索股票代码数据并将其反馈给指示器

然而,我注意到UI在不规则的时间间隔内变得不负责任。我假设这是因为HTTP请求(带有请求库)被阻塞。所以我决定在自己的线程中启动每个指示器,但一旦所有的指示器都加载完毕,同样的问题仍然会发生。(我不明白为什么,如果某个线程本身有问题,它就不应该阻塞主线程?)

然后我尝试用grequests替换请求,但是我无法让它工作,因为回调似乎从未被调用过。似乎也有类似承诺的东西,但所有这些的文档看起来都过时了,而且不完整

代码:


线程中运行HTTP
可以更好地显示代码。可能在新线程中,您使用GUI元素在GUI中阻止
mainloop
,或者您向主线程发送数据,当GUI接收数据时,它阻止
mainloop
。我检查了您的大多数文件,发现
import threading
仅在
coin/indicator.py
中存在,但您从未使用它创建新线程。那个么你们在哪里创建那个些线程呢?我不确定你们应该在线程中运行指示器,因为它是ogf GUI的一部分。线程应该只下载数据。
Gtk.main()
运行循环,从系统获取事件,将事件发送到小部件,重新绘制小部件。如果它被阻止了,那么它就不能刷新窗口小部件,并且看起来它冻结了。它一直工作,直到你关上窗户。您必须在
Gtk.main()
之前或使用GUI中的按钮启动GUI之后运行其他线程。或者您可以使用
thread.Timer()
Gtk.main()
之前创建它,但它将在
Gtk.main()
启动之后启动。
# necessary imports here

class Coin(Object):
    self.start_main()
    self.instances = []

    def start_main(self):
        self.main_item = AppIndicator.Indicator.new(name, icon)
        self.main_item.set_menu(self._menu()) # loads menu and related actions (code omitted)

    def add_indicator(self, settings=None):
        indicator = Indicator(self, len(self.instances), self.config, settings)
        self.instances.append(indicator)
        nt = threading.Thread(target=indicator.start())
        nt.start()

    def _add_ticker(self, widget): # this is clickable from the menu (code omitted)
        self.add_indicator('DEFAULTS')

class Indicator():
    instances = []

    def __init__(self, coin, counter, config, settings=None):
        Indicator.instances.append(self)

    def start(self):
        self.indicator = AppIndicator.Indicator.new(name + "_" + str(len(self.instances)), icon)
        self.indicator.set_menu(self._menu())
        self._start_exchange()

    def set_data(self, label, bid, high, low, ask, volume=None):
        # sets data in GUI

    def _start_exchange(self):
        exchange = Kraken(self.config, self)
        exchange.check_price()
        exchange.start()

class Kraken:
  def __init__(self, config, indicator):
    self.indicator = indicator
    self.timeout_id = 0

  def start(self):
    self.timeout_id = GLib.timeout_add_seconds(refresh, self.check_price)

  def stop(self):
    if self.timeout_id:
      GLib.source_remove(self.timeout_id)

  def check_price(self):
    res = requests.get('https://api.kraken.com/0/public/Ticker?pair=XXBTZUSD')
    data = res.json()
    self._parse_result(data['result'])

  def _parse_result(self, data):
    # code to parse json result
    self.indicator.set_data(label, bid, high, low, ask)

coin = Coin()
Gtk.main()