1

I am working on an Ubuntu Appindicator that displays the value of a JSON API call every X seconds.

The issue is that, randomly, it will stop calling self.loop without any error or warning. I can have it running for days or for hours. I've setup (in development) debug statements and it always stops running after the loop function is called.

It's as if I was returning False or not returning from the function even though the logic in this code should always return True.

Here is the documentation for GObject.timeout_add (for GTK2 but the principle stands).

I'm not sure if it's dependent on the PyGTK version. I've had it happen in Ubuntu 16.04 and Ubuntu 17.04.

Here is the full class. The point where the JSON API is called is at result = self.currency.query(). I am happy to give further feedback.

import gi

gi.require_version('Gtk', '3.0')
from gi.repository import GObject


class QueryLoop():
    """QueryLoop accepts the indicator to which the result will be written and an currency to obtain the results from.
    To define an currency you only need to implement the query method and return the results in a pre-determined
    format so that it will be consistent."""
    def __init__(self, indicator, currency, timeout=5000):
        """
        Initialize the query loop with the indicator and the currency to get the data from.
        :param indicator: An instance of an indicator
        :param currency: An instance of an currency to get the information from
        :param timeout The interval between requests to the currency API
        """
        self.indicator = indicator
        self.currency = currency
        self.timeout = timeout
        self.last_known = {"last": "0.00"}

    def loop(self):
        """Loop calls it-self forever and ever and will consult the currency for the most current value and update
        the indicator's label content."""
        result = self.currency.query()

        if result is not None:
            self.indicator.set_label("{} {}".format(result["last"], self.currency.get_ticker()))
            self.last_known = result
        else:
            self.indicator.set_label("Last Known: {} EUR (Error)".format(self.last_known["last"]))

        return True

    def start(self):
        """Starts the query loop it does not do anything else. It's merely a matter of naming because
        when initializing the loop in the main() point of entry."""
        GObject.timeout_add(self.timeout, self.loop)
        self.loop()
Ricardo Velhote
  • 4,630
  • 1
  • 24
  • 30
  • 2
    if self.currency.query() blocks, then it will never return. Which method is that and also self.currency.get_ticker() ? – José Fonte Jun 09 '17 at 11:08
  • 1
    Side note, correct docs are here: http://lazka.github.io/pgi-docs/index.html – TingPing Jun 10 '17 at 01:03
  • Thank you for your inputs. @JoséFonte `get_ticker()` just returns a string. It does not call external resources. You are correct in saying that `self.currency.query()` could block and never return however I've placed logs in every line and it never once stopped in `self.currency.query()`. I am puzzled by this :S – Ricardo Velhote Jun 11 '17 at 16:34
  • 1
    @RicardoVelhote So the problem resides on self.currency.query(). You mentioned that the application works but randomly stops... maybe there's some situations where the method blocks. Does it resume later on? is that a socket operation? Does it have timeouts? make a dummy query method and check if the application works fine. – José Fonte Jun 13 '17 at 10:10
  • @JoséFonte I never thought that the timeout could be the issue however I read the [Requests](http://docs.python-requests.org/en/master/user/quickstart/#timeouts) documentation again and they mention specifically that `Failure to do so [specifying the timeout] can cause your program to hang indefinitely`. I will give it a try. Thank you! – Ricardo Velhote Jun 17 '17 at 10:53
  • @JoséFonte The timeout was indeed the root cause because I'm seeing a rare `ConnectTimeoutError` exception - the documentation made it clearer. Thank you so much for your observations which were very valuable. If you want, go ahead and create an answer otherwise I'll do it myself in a few days. – Ricardo Velhote Jun 18 '17 at 13:58
  • @RicardoVelhote Glad that you have solved it. Feel free to write the answer. You will have more insights on the right python code. Thanks though. Obrigado e boa sorte ;) – José Fonte Jun 18 '17 at 14:15

0 Answers0