Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kivy - threads, queues, clocks and Python sockets

Tags:

kivy

I'm brand new to Kivy, and also new to GUI, but not new to programming.

I am completely missing the boat, the canoe, and the airplane on using Kivy.

In 30 years of programming, from machine code, assembly, Fortran, C, C++, Java, Python, I've never tried to use a language such as Kivy who's documentation is this thin, because it's so new. I know it'll get better, but I'm trying to use it now.

In my code, I'm trying to implement Queueing, so that I can obtain Python socket data. In normal Python programming, I would have IPC via a Queue - put data in, get data out.

I understand from Kivy, mostly from what I've read in various forums, but can't say I've found it in the documentation at kivy.org, that I can't do the following:

  • Kivy needs to be in it's own thread.
  • Nothing in Kivy should sleep.
  • Nothing in Kivy should do blocking IO.

After a LOT of Google searching, the only thing I've actually found that approaches being useful, is an informative note here on StackOverFlow . However, while it almost solves my problem, the answer assumes I know more about Kivy than I do; I don't know how to incorporate the answer.

If someone could take the time to put together a COMPLETE short demo of using that example, or one of your own unique COMPLETE answers, I would much appreciate it!

Here's some short code I put together, but it doesn't work, because it blocks on the get() call.

from Queue import Queue
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.clock import Clock
from threading import Thread

class ClockedQueue(BoxLayout):
    text1 = StringProperty("Start")

    def __init__(self):
        super(ClockedQueue,self).__init__()
        self.q = Queue()
        self.i=0
        Clock.schedule_interval(self.get, 2)

    def get(self,dt):
        print("get entry")

        val = self.q.get()
        print(self.i + val)
        self.i += 1

class ClockedQueueApp(App):

    def build(self):
        return ClockedQueue()

class SourceQueue(Queue):
    def __init__(self):
        q = Queue()
        for word in ['First','Second']:
            q.put(word)
        print("SourceQueue finished.")

def main():

    th = Thread(target=SourceQueue)
    th.start()

    ClockedQueueApp().run()
    return 0

if __name__ == '__main__':


    main()

Thanks!

like image 323
user3621831 Avatar asked May 09 '14 20:05

user3621831


1 Answers

Here's some short code I put together, but it doesn't work, because it blocks on the get() call.

So what you really want to do is get items from your queue in a non-blocking way?

There are multiple ways to do this. The simplest seems to be to just check if the queue has any items before getting one - Queue has several methods that help with this, including checking if it is empty or setting whether get is allowed to be blocking (by setting its first argument to False). If you just do this instead of calling get on its own, you won't block things waiting for the queue to have any items - if it's empty or you can't immediately get anything, you just do nothing.

I don't know what you want to do with the items you get from the queue, but if it's short operations that don't take long then you won't need anything more than this. For instance, you could Clock.schedule_interval the get method to happen every frame, do nothing if the queue is empty, or operate on the data if you get something back. No blocking, and no messing with your own threads.

You can also create your own thread and run the blocking code in it, which is general way to deal with blocking issues, especially tasks that can't be split up into short sections that can be performed between frames. I don't know about the details of this, but it should just involve using python threads normally. You can check the source of kivy's UrlRequest for an example, this can download a web source in a background thread.

Edit: Also your SourceQueue is messed up (you override its __init__ to make a new queue that you don't store anywhere), and your clock scheduling has a meaningless third argument false which isn't even defined. I don't know what's going on here, it probably affects what you're trying to do, but doesn't matter to my general answer above.

like image 116
inclement Avatar answered Jan 03 '23 11:01

inclement