Pausing a program - poll/sleep/threads?

Discussion in 'Python' started by Simon John, Feb 17, 2005.

  1. Simon John

    Simon John Guest

    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....
     
    Simon John, Feb 17, 2005
    #1
    1. Advertising

  2. Simon John

    Paul Rubin Guest

    "Simon John" <> writes:
    > 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)?


    See the signal module and use the alarm signal.
     
    Paul Rubin, Feb 17, 2005
    #2
    1. Advertising

  3. Simon John

    Harlin Guest

    import time

    play_something()

    time.sleep(LengthOfSongInSeconds)

    do_something()


    Have you tried that? I'd be interesting in seeing this app you have. !
     
    Harlin, Feb 17, 2005
    #3
  4. Simon John

    Simon John Guest

    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....
     
    Simon John, Feb 17, 2005
    #4
  5. Simon John

    Simon John Guest

    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....
     
    Simon John, Feb 17, 2005
    #5
  6. Simon John

    Jeff Shannon Guest

    Simon John wrote:

    > 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)?


    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
     
    Jeff Shannon, Feb 17, 2005
    #6
  7. Simon John

    Simon John Guest

    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....
     
    Simon John, Feb 17, 2005
    #7
  8. Simon John

    Jeff Shannon Guest

    Simon John wrote:

    > 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 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. :)

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


    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?

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


    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
     
    Jeff Shannon, Feb 17, 2005
    #8
  9. Simon John

    Simon John Guest

    Jeff Shannon wrote:

    [snip]
    > 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. :)


    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....

    [...]
    > 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?


    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!)

    [...]
    > 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?


    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.

    [...]
    > 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.


    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.
     
    Simon John, Feb 18, 2005
    #9
  10. Simon John

    Simon John Guest

    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(Thread):
    """overloads 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):
    """referencing 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.mainTextarea.setText(self.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?
     
    Simon John, Feb 19, 2005
    #10
  11. Simon John

    Simon John Guest

    Simon John, Feb 19, 2005
    #11
  12. Simon John

    Jarek Zgoda Guest

    Simon John napisa³(a):

    > Damn, seems Qt GUI objects (windgets) aren't thread-safe:
    >
    > http://doc.trolltech.com/3.3/threads.html#11


    Like most (if not all) others GUI toolkits.

    > 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/python-list/2002-February/089360.html


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

    --
    Jarek Zgoda
    http://jpa.berlios.de/ | http://www.zgodowie.org/
     
    Jarek Zgoda, Feb 19, 2005
    #12
  13. Simon John

    Simon John Guest

    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
    ;-)
     
    Simon John, Feb 21, 2005
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bryan R. Meyer

    Pausing Threads From Events

    Bryan R. Meyer, Apr 27, 2004, in forum: Java
    Replies:
    16
    Views:
    1,507
    NOBODY
    Apr 30, 2004
  2. Aaron J. M.

    Pausing and Unpausing Threads

    Aaron J. M., Aug 12, 2007, in forum: Python
    Replies:
    6
    Views:
    272
    Aaron J. M.
    Aug 13, 2007
  3. anita
    Replies:
    7
    Views:
    2,600
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=
    Sep 1, 2007
  4. birdsong

    select.poll.poll() never blocks

    birdsong, Feb 12, 2009, in forum: Python
    Replies:
    2
    Views:
    472
    birdsong
    Feb 12, 2009
  5. Jean-Paul Calderone

    Re: select.poll.poll() never blocks

    Jean-Paul Calderone, Feb 12, 2009, in forum: Python
    Replies:
    3
    Views:
    460
    birdsong
    Feb 12, 2009
Loading...

Share This Page