Pausing a program - poll/sleep/threads?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Simon John

    Pausing a program - poll/sleep/threads?

    I'm writing a PyQt network client for XMMS, using the InetCtrl plugin,
    that on connection receives a track length.

    To save on bandwidth, I don't want to be continually querying the
    server for updates (e.g. has the current track finished yet?) so I
    figured the best thing to do is just update after the track length has
    expired.

    So, how would I make a Python program automatically call a function
    after a preset period of time, without the Python process running in
    the foreground (effectively single-tasking)?

    I think that sleep() would work in the foreground (kind of like a while
    loop does, I've come across that issue with wxPython!) does Python have
    any polling capabilities?

    What about threading - if I launched a thread to just "wait" until a
    time has expired, could I then get that thread to make the main program
    call a function, or would the main program sit there waiting for the
    thread to end? I really have no experience with threads in Python, any
    hints/tutorials, the docs are pretty limited?

    I'm looking to make this program cross-platform, it has to run on at
    least Windows and Linux (hopefully MacOSX too) so the solution would
    have to be portable (does Windows even have threading without POSIX?)

    If you want to check out what I've done so far (GUI, track info,
    controls etc.) you'll need XMMS, http://inetctrl.sourceforge.net and my
    source from http://www.the-jedi.co.uk/downloads/xmmsclient there's also
    some Windows binaries built with the Cygwin/KDE port.

    [InetCtrl seems to segfault if you don't have a playlist loaded, so
    load a playlist first, then enable the general plugin. I must submit a
    bug report to the author, maybe I could convince him to broadcast when
    a track ends...]

    Any help would be excellent, as playlist support and these "timed
    updates" are about all that's left needing to be done....

  • Paul Rubin

    #2
    Re: Pausing a program - poll/sleep/threads?

    "Simon John" <simoninusa2001 @yahoo.co.uk> writes:[color=blue]
    > So, how would I make a Python program automatically call a function
    > after a preset period of time, without the Python process running in
    > the foreground (effectively single-tasking)?[/color]

    See the signal module and use the alarm signal.

    Comment

    • Harlin

      #3
      Re: Pausing a program - poll/sleep/threads?

      import time

      play_something( )

      time.sleep(Leng thOfSongInSecon ds)

      do_something()


      Have you tried that? I'd be interesting in seeing this app you have. !

      Comment

      • Simon John

        #4
        Re: Pausing a program - poll/sleep/threads?

        I don't think time.sleep() will work too well, I think it will cause
        the program to hang around in the foreground, and prevent the GUI
        updating.

        I'll give it a try just to make sure, as I can't figure out the
        signal/alarm thing (the alarm only seems to trigger when I click a
        button, not after n-seconds....

        Comment

        • Simon John

          #5
          Re: Pausing a program - poll/sleep/threads?

          Damn! signal is not supported on Windows.

          time.sleep() doesn't work, as I suspected::

          def info(self):
          sleep(5)
          self.info()

          Basically causes the function to pause, then call itself again, all in
          the foreground :-(

          I'm thinking some sort of thread timer is the way to go, but really
          don't understand threads....

          Comment

          • Jeff Shannon

            #6
            Re: Pausing a program - poll/sleep/threads?

            Simon John wrote:
            [color=blue]
            > I'm writing a PyQt network client for XMMS, using the InetCtrl plugin,
            > that on connection receives a track length.
            >
            > [...]
            >
            > So, how would I make a Python program automatically call a function
            > after a preset period of time, without the Python process running in
            > the foreground (effectively single-tasking)?[/color]

            I'm not familiar with Qt/PyQt myself, but the GUI toolkits I *am*
            familiar with all have a concept of a timer. Basically, you create a
            timer that, when the specified amount of time has elapsed, will either
            deliver an event/message to your application's event queue or will
            directly call the callback function you provide.

            However, I'd suggest that you may not want to wait for the entire
            length of the current track, especially if some other process or user
            (on any machine) may have access to the same XMMS application. What
            happens when, after the song's been playing for a few seconds, someone
            skips to the next track? Presumably, you'll want your network client
            to detect that and update appropriately. This implies that you should
            check back in with the XMMS "server" every few seconds at least. (You
            can still use a timer to do this; just have it fire periodically every
            second or so, rather than only after several minutes.)

            Jeff Shannon

            Comment

            • Simon John

              #7
              Re: Pausing a program - poll/sleep/threads?

              Hmm, yes I had thought of looking around PyQt for a timer, forgot about
              it though.

              As far as querying the server every few seconds, it does make sense
              (you don't miss events) and is the recommended way of doing things with
              InetCtrl, but I'd prefer to save the bandwidth/server load than have
              realtime status updates.

              The status also updates whenever you send a command (like play/pause).

              I'm really stuck on how to implement this now....

              Comment

              • Jeff Shannon

                #8
                Re: Pausing a program - poll/sleep/threads?

                Simon John wrote:
                [color=blue]
                > As far as querying the server every few seconds, it does make sense
                > (you don't miss events) and is the recommended way of doing things with
                > InetCtrl, but I'd prefer to save the bandwidth/server load than have
                > realtime status updates.[/color]

                The amount of bandwidth and server load that will be used by a
                once-a-second query is probably pretty trivial (unless you're
                expecting this to run over internet or dialup networks -- and even
                then, it's probably not going to be worth worrying about). Even on an
                old 10Mbit ethernet connection, a couple of extra packets every second
                will not make a notable difference. This (IMO) is premature
                optimization. :)
                [color=blue]
                > The status also updates whenever you send a command (like play/pause).[/color]

                But does the server push events to the client? If there's a
                filesystem error while a track is playing, how does your client know
                about it? In addition, what happens if XMMS segfaults, or the server
                machine loses power?
                [color=blue]
                > I'm really stuck on how to implement this now....[/color]

                One of the big questions here is whether your client will have
                exclusive access to the XMMS server. That is, will it be possible for
                more than one such client to connect to the same XMMS, and/or for XMMS
                to have direct interaction on its host machine?

                If you have exclusive access, then changes in the status of XMMS will
                only happen when 1) you change it yourself, or 2) there is an error.
                In this case, you can check status much less often. (However, you'll
                still want to deal with the error conditions, which probably means
                checking at a much shorter interval than expected track length.) If,
                on the other hand, there may be more than one client/user interacting
                with XMMS, then you also have to deal with the possibility of your
                server changing status without your client taking direct action.

                I really think that you *do* want to do fairly frequent status checks
                with your server. The cost is small, and the gains in responsiveness
                and robustness are potentially very significant.

                Jeff Shannon


                Comment

                • Simon John

                  #9
                  Re: Pausing a program - poll/sleep/threads?

                  Jeff Shannon wrote:

                  [snip][color=blue]
                  > The amount of bandwidth and server load that will be used by a
                  > once-a-second query is probably pretty trivial (unless you're
                  > expecting this to run over internet or dialup networks -- and even
                  > then, it's probably not going to be worth worrying about). Even on[/color]
                  an[color=blue]
                  > old 10Mbit ethernet connection, a couple of extra packets every[/color]
                  second[color=blue]
                  > will not make a notable difference. This (IMO) is premature
                  > optimization. :)[/color]

                  It is designed to work over 802.11b (so under 11Mbit).

                  I'm going to fire up Ethereal later and see how much traffic this would
                  cause, most of the commands are only about 30bytes long, and the
                  longest response would be the filename, it just seems to me that
                  polling a server once every second or two, is kinda like a DDoS....

                  [...][color=blue]
                  > But does the server push events to the client? If there's a
                  > filesystem error while a track is playing, how does your client know
                  > about it? In addition, what happens if XMMS segfaults, or the server[/color]
                  [color=blue]
                  > machine loses power?[/color]

                  No, this is not server push, the client must query the server. Plus the
                  InetCtrl plugin does seem to segfault quite a lot, resulting in a
                  socket exception - I'll have to make sure that the client stops
                  querying the server after a socket excption, and doesn't keep trying
                  (resulting in lots of error dialogs!)

                  [...][color=blue]
                  > One of the big questions here is whether your client will have
                  > exclusive access to the XMMS server. That is, will it be possible[/color]
                  for[color=blue]
                  > more than one such client to connect to the same XMMS, and/or for[/color]
                  XMMS[color=blue]
                  > to have direct interaction on its host machine?[/color]

                  No, you can have multiple connections to the server, and you can use
                  XMMS directly, so it would be possible for the client to miss events.

                  [...][color=blue]
                  > I really think that you *do* want to do fairly frequent status checks[/color]
                  [color=blue]
                  > with your server. The cost is small, and the gains in responsiveness[/color]
                  [color=blue]
                  > and robustness are potentially very significant.[/color]

                  Yes, I'm coming around to this POV too, but I still don't know how to
                  implement it (querying every 2 seconds say) in a multi-tasking manor -
                  as I said, sleep() hangs up the GUI, and alarm() is not portable....

                  Thanks for your suggestions.

                  Comment

                  • Simon John

                    #10
                    Re: Pausing a program - poll/sleep/threads?

                    OK, I've implemented the 2sec threaded update, but I'm having some
                    problems with it.

                    Basically the thread will have to just run constantly, never exiting
                    (just sleeping for 2secs), which seems to work OK except when I try to
                    get the thread to do anything with the main program's window.

                    As the thread doesn't end, it doesn't return a result, so on every pass
                    of the thread's while loop, I write the current track info to the
                    mainWindow directly, however this causes the program to hang. Here is a
                    snippet of the current method:

                    class ThreadedInfo(Th read):
                    """overload s init and defines run"""
                    def __init__(self):
                    Thread.__init__ (self)

                    def run(self):
                    # runs the whole time
                    while 1:
                    self.info()
                    time.sleep(2)

                    def info(self):
                    """referenc ing window kills linux here"""

                    # get track info, returned as dictionary
                    self.info_dict = backend.getInfo (config.server, config.port)

                    I was thinking of getting the thread to just run once, then getting the
                    main program to write the result (using join() ) to the mainWindow.
                    That method would be something like this, but it's almost totally
                    pointless using a thread then, as the while loop will singletask the
                    program:

                    while 1:
                    # start thread
                    self.infothread .start()

                    # when thread ends, get result
                    self.result = self.infothread .join()

                    # write result to window
                    window.mainText area.setText(se lf.result)

                    # pause for 2secs before starting again
                    sleep(2)

                    I made sure that I built PyQt using threads, so that's not the issue.
                    Any other ideas?

                    Comment

                    • Simon John

                      #11
                      Re: Pausing a program - poll/sleep/threads?

                      Damn, seems Qt GUI objects (windgets) aren't thread-safe:



                      So I'm going to have to find a way of using a thread to fetch the data,
                      and then using the main program to update the GUI... Someone suggested
                      using events:



                      Comment

                      • Jarek Zgoda

                        #12
                        Re: Pausing a program - poll/sleep/threads?

                        Simon John napisa³(a):
                        [color=blue]
                        > Damn, seems Qt GUI objects (windgets) aren't thread-safe:
                        >
                        > http://doc.trolltech.com/3.3/threads.html#11[/color]

                        Like most (if not all) others GUI toolkits.
                        [color=blue]
                        > So I'm going to have to find a way of using a thread to fetch the data,
                        > and then using the main program to update the GUI... Someone suggested
                        > using events:
                        >
                        > http://mail.python.org/pipermail/pyt...ry/089360.html[/color]

                        See http://www.informit.com/articles/pri...ly.asp?p=30708

                        --
                        Jarek Zgoda
                        http://jpa.berlios.de/ | http://www.zgodowie.org/

                        Comment

                        • Simon John

                          #13
                          Re: Pausing a program - poll/sleep/threads?

                          Ah yes, that Informit article helped endlessly - I'm all done now - got
                          the backend to fetch the info from the server every 2secs using a
                          QThread, then it pass the data back to the GUI frontend by raising a
                          custom event!

                          Thanks for all the help folks, now I'm off to compile the new PyQt 3.14
                          ;-)

                          Comment

                          Working...