473,508 Members | 2,006 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Command config, quitting, binary, Timer

Hello, I have four things to ask or to suggest, sorry if they seem
basic or already discussed.

-------------------

I am still ignorant about Tkinter. This little program, after pressing
the "Go" eats more and more RAM, is it normal? Can it be avoided? (In
normal programs this is isn't a real problem).

! import Tkinter
! def dogo():
! while 1:
! b.config(command=lambda:None)
! root = Tkinter.Tk()
! b = Tkinter.Button(root, text="Go", command=dogo)
! b.pack()
! root.mainloop()

Note: I have found this problem because in a small program I have a
Start button that becomes a Stop, so the bound command must change each
time. (Maybe there is some other solution, like hiding/unhiding the
buttons, I don't know.)

-------------------

When I quit a Tkinter program (clicking the [X] button of the window)
while it's running, it stops with something like this:

TclError: invalid command name ".9970192"

There is a way to avoid it, or to intercept that quitting command to
stop the program more gracefully?

-------------------

When I have to convert numbers to binary I use something like this (the
management of negative numbers is removed). It's my faster Python
version (derived by a Hettinger's version):

! from collections import deque
! def binary_conv(n):
! if n == 0:
! return 0
! else:
! absn = abs(n)
! conv = ["0", "1"]
! result = deque()
! _app = result.appendleft
! while absn:
! _app( conv[absn & 1] )
! absn >>= 1
! return int("".join(result))

But converting to binary is a quite common operation, so I think it can
be added as a binary function to Python, for example adding "b" to the
the conversion types of the % formatting.

-------------------

Sometimes I need something like the Timer of Java, it generates "ticks"
and calls a function for each tick. The tick frequency can be set, or
they can be stopped.

In another Newsgroup someone has suggested me that the callLater of
Twisted can solve my problem, but I think it's a quite common thing, so
I think that maybe it can be added to the threading standard module.

This is a rough Python version of mine (without comments), it's not a
true Metronome because it counts the delay time after the end of the
last function call. This class also seems fragile, sometimes it gives
me problems, and I cannot use too much concurrent metronomes, etc. It's
quite

Maybe someone can suggest me how to improve it.
! from threading import Timer
!
! class Metronome(object):
! def __init__(self, interval, fun, *args, **kwargs):
! self.interval = interval # seconds.
! self.fun = fun
! self.args = args
! self.kwargs = kwargs
! self._running = False
! def _go(self):
! # Call the function with the stored values
! self.fun(*self.args, **self.kwargs)
! if self._running:
! self._call = Timer(self.interval, self._go)
! self._call.start()
! def start(self):
! if not self._running:
! self._running = True
! self._go()
! def stop(self):
! if self._running:
! self._call.cancel()
! self._running = False

Thank you,
bearophile

Sep 4 '05 #1
8 2151
be************@lycos.com wrote:
I am still ignorant about Tkinter. This little program, after pressing
the "Go" eats more and more RAM, is it normal? Can it be avoided? (In
normal programs this is isn't a real problem).

! import Tkinter
! def dogo():
! while 1:
! b.config(command=lambda:None)
! root = Tkinter.Tk()
! b = Tkinter.Button(root, text="Go", command=dogo)
! b.pack()
! root.mainloop()


What did you expect to happen with the infinite loop inside dogo()?
Wouldn't it call b.config() over and over again, never returning? Is
that really what you wanted?

-Peter
Sep 4 '05 #2
On 3 Sep 2005 18:44:11 -0700, be************@lycos.com declaimed the
following in comp.lang.python:

! import Tkinter
! def dogo():
! while 1:
! b.config(command=lambda:None)
Well, this infinite loop can't be good for memory usage (I'm no
expert -- what does .config() do? [If I interpret the skimpy help
system, basically this one is replacing the original "dogo" method with
an anonymous function that "returns" None -- being in an endless loop,
you are creating an endless number of anonymous functions; they may not
be garbage collected until the loop ends]
Note: I have found this problem because in a small program I have a
Start button that becomes a Stop, so the bound command must change each
time. (Maybe there is some other solution, like hiding/unhiding the
buttons, I don't know.)
Would it not be easier to have a single callback, but change the
button Label, and have the callback branch based on the current label?
-------------------

When I quit a Tkinter program (clicking the [X] button of the window)
while it's running, it stops with something like this:

TclError: invalid command name ".9970192"

There is a way to avoid it, or to intercept that quitting command to
stop the program more gracefully?
No idea -- my only Tkinter program (at work, so I can't test it),
doesn't do anything like this. -------------------

When I have to convert numbers to binary I use something like this (the
management of negative numbers is removed). It's my faster Python
version (derived by a Hettinger's version):

! from collections import deque
! def binary_conv(n):
! if n == 0:
! return 0
! else:
! absn = abs(n)
! conv = ["0", "1"]
! result = deque()
! _app = result.appendleft
! while absn:
! _app( conv[absn & 1] )
! absn >>= 1
! return int("".join(result))

But converting to binary is a quite common operation, so I think it can
be added as a binary function to Python, for example adding "b" to the
the conversion types of the % formatting.
Ugh...

And exactly what are you trying to return? That last line implies
you are returning an integer... If I understand the logic, you are
taking, say an integer of 3 (in binary "00000011"b, assuming only a byte
in length), creating a string of 0/1 ("11"), and then converting this
string back to an integer with the value 11 (binary "10000011")...
NYBBLES = { "0" : "0000",
"1" : "0001",
"2" : "0010",
"3" : "0011",
"4" : "0100",
"5" : "0101",
"6" : "0110",
"7" : "0111",
"8" : "1000",
"9" : "1001",
"A" : "1010",
"B" : "1011",
"C" : "1100",
"D" : "1101",
"E" : "1110",
"F" : "1111" }

def conv2b(n):
tstr = "%X" % n
olst = []
for nyb in tstr:
olst.append(NYBBLES[nyb])
return "".join(olst)

print
print "3 is ", conv2b(3)
print "11 is ", conv2b(11)
print "3.141 is ", conv2b(3.141)
print "-3 is ",conv2b(-3)
print "40558 is ", conv2b(40558)

-=-=-=-=-=-=-
3 is 0011
11 is 1011
3.141 is 0011
E:\UserData\Dennis Lee Bieber\My Documents\Python Progs\Script1.py:20:
FutureWarning: %u/%o/%x/%X of negative int will return a signed string
in Python 2.4 and up
tstr = "%X" % n
-3 is 11111111111111111111111111111101
40558 is 1001111001101110

I've not tested it, but I somehow suspect it is faster than a mass
of push/pop and shifts...


-------------------

Sometimes I need something like the Timer of Java, it generates "ticks"
and calls a function for each tick. The tick frequency can be set, or
they can be stopped.

In another Newsgroup someone has suggested me that the callLater of
Twisted can solve my problem, but I think it's a quite common thing, so
I think that maybe it can be added to the threading standard module.

This is a rough Python version of mine (without comments), it's not a
true Metronome because it counts the delay time after the end of the
last function call. This class also seems fragile, sometimes it gives
me problems, and I cannot use too much concurrent metronomes, etc. It's
quite
Main problem I see with this is that each call to threading.Timer()
is creating a NEW thread just for one tick. Lots of overhead involved.
I'd create a single thread whose main run method is a continuous loop,
using time.sleep() to suspend between ticks. .Timer() is optimized for a
one-time callback.

Note that using _nextInterval allows me perform an adjustment for
the time taken by the callback function.

-=-=-=-=-=-=-
import time
import threading

class Metronome(object):
def __init__(self, interval, func, *args, **kwargs):
self._func = func
self._args = args
self._kwargs = kwargs
self._interval = interval
self._running = False
self._Timer = None
self._nextInterval = 0

def Start(self):
if not self._running:
print "Creating worker at %s" % time.time()
self._Timer = threading.Thread(None, self._worker, (), {})
self._nextInterval = time.time() + self._interval
self._running = True
self._Timer.start()

def Stop(self):
if self._running:
print "Stopping worker at %s" % time.time()
self._running = False
self._Timer.join()
print "thread joined"

def _worker(self):
while self._running:
time.sleep(self._nextInterval - time.time())
self._nextInterval += self._interval
self._func(*self._args, **self._kwargs)
def aTick():
print "A tick happened at: %s" % time.time()

if __name__ == "__main__":
m = Metronome(5.0, aTick)
m.Start()
time.sleep(30)
m.Stop()
time.sleep(2.5)
m.Start()
time.sleep(20)
m.Stop()
-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Sep 4 '05 #3
> ! import Tkinter
! def dogo():
! while 1:
! b.config(command=lambda:None)
! root = Tkinter.Tk()
! b = Tkinter.Button(root, text="Go", command=dogo)
! b.pack()
! root.mainloop()

I guess tkinter has to keep a name-reference pair (some days a
discussion about this arose and /F said something like that). It
certainly is somewhat ugly - but there might be very good reasons to do so.
Note: I have found this problem because in a small program I have a
Start button that becomes a Stop, so the bound command must change each
time. (Maybe there is some other solution, like hiding/unhiding the
buttons, I don't know.)
Had that to do myself - my solution was to use the buttons text for
swich-casing. I guess you change the buttons text anyways (otherwise
nobody would know that its semantic changed), so do something like this
(untetsted)

def start_stop_callback():
if b.get_config("text") == "Start":
b.config(text="Stop")
....
else:
b.config(text="Start")
....

Sometimes I need something like the Timer of Java, it generates "ticks"
and calls a function for each tick. The tick frequency can be set, or
they can be stopped.

In another Newsgroup someone has suggested me that the callLater of
Twisted can solve my problem, but I think it's a quite common thing, so
I think that maybe it can be added to the threading standard module.

This is a rough Python version of mine (without comments), it's not a
true Metronome because it counts the delay time after the end of the
last function call. This class also seems fragile, sometimes it gives
me problems, and I cannot use too much concurrent metronomes, etc. It's
quite

Maybe someone can suggest me how to improve it.


Instead of several metronomes, use one thread and compute the gresatest
common divisor for all scheduled timings. Use that as sleep interval
(your "ticks"), and count ticks for each timer. You should introduce a
lower thrshold on tick-length, otherwise you can get into trouble.
Diez
Sep 4 '05 #4
Witn your suggestions and with some tests and work I've solved most of
the problems, thank you all for the comments.

Peter Hansen:
What did you expect to happen with the infinite loop inside dogo()?<
I expected that the same memory used by the b.config(command=...) can
be used by the successive update of the command. I am ignorant about
Tkinter, but to me it seems that no new memory is really needed each
loop.

-------------------

Dennis Lee Bieber:
you are creating an endless number of anonymous functions; they may not be garbage collected until the loop ends<
I don't know, usually the garbage collector is quite efficient :-)

Would it not be easier to have a single callback, but change the button Label, and have the callback branch based on the current label?<
Right, thank you. It's not a perfect solution, but often it's good
enough.

No idea -- my only Tkinter program (at work, so I can't test it), doesn't do anything like this.<
With more tests and some googling I have found the problem and the
solution. It seems that the problem was produced by commands like this:
self.canvas.delete(self.id)
Maybe they are called after the Tkinter stop, or window close, or
something like that.

To solve the problem I've added this to the main window:
self.root.protocol('WM_DELETE_WINDOW', self.quitAll)

And inside the self.quitAll method I fix something before calling
self.root.quit()

I somehow suspect it is faster than a mass of push/pop and shifts...<
Your version is very interesting, thank you. I'll use this modified
version:

! _nibbles = {"0":"0000", "1":"0001", "2":"0010", "3":"0011",
! "4":"0100", "5":"0101", "6":"0110", "7":"0111",
! "8":"1000", "9":"1001", "A":"1010", "B":"1011",
! "C":"1100", "D":"1101", "E":"1110", "F":"1111",
! "-":"-"}
!
! def to_base2(number):
! result = [_nibbles[nibble] for nibble in "%X"%number]
! return int("".join(result))

This is faster than my version (but if you are using Psyco for all the
tests, for small numbers my version is faster).
This version is expecially faster for very long numbers.
But the difference between the two versions is quite little still, a C
function like the base2 conversion of GMPY is much faster, so I think
that such common operation can be added to the % formatting sintax.

Main problem I see with this is that each call to threading.Timer() is creating a NEW thread just for one tick. Lots of overhead involved. I'd create a single thread whose main run method is a continuous loop, using time.sleep() to suspend between ticks. .Timer() is optimized for a one-time callback. Note that using _nextInterval allows me perform an adjustment for the time taken by the callback function.<
Oh, very nice, you are very gentle, thank you. I'll add few suggestion
by Roggisch, and I think it will be quite good. If I obtain something
good I'll even think about putting it in the cookbook (with your names
in it).

-------------------

Diez B. Roggisch:
It certainly is somewhat ugly - but there might be very good reasons to do so.<
Okay.

Instead of several metronomes, use one thread and compute the gresatest common divisor for all scheduled timings. Use that as sleep interval (your "ticks"), and count ticks for each timer. You should introduce a lower thrshold on tick-length, otherwise you can get into trouble.<


Okay, I'll follow your suggestions.

Thank you all and hugs to Dennis Lee Bieber,
bearophile

Sep 4 '05 #5
On 4 Sep 2005 08:48:33 -0700, be************@lycos.com declaimed the
following in comp.lang.python:

you are creating an endless number of anonymous functions; they may not be garbage collected until the loop ends<
I don't know, usually the garbage collector is quite efficient :-)

Yes, but only when ref-counts go to 0... it may be that this tight
loop never allowed stuff to go to 0 ref-counts. It definitely never
returned control, so besides eating memory that way, any events for the
GUI framework were also not being handled and had to be queued.
Your version is very interesting, thank you. I'll use this modified
version:

! _nibbles = {"0":"0000", "1":"0001", "2":"0010", "3":"0011",
! "4":"0100", "5":"0101", "6":"0110", "7":"0111",
! "8":"1000", "9":"1001", "A":"1010", "B":"1011",
! "C":"1100", "D":"1101", "E":"1110", "F":"1111",
! "-":"-"}
!
! def to_base2(number):
! result = [_nibbles[nibble] for nibble in "%X"%number]
! return int("".join(result))
I'm still concerned about your use of that int() call... What is the
real use case for this conversion?

You take in a number -- which, for all but a few languages, is
internally binary (the exceptions being: true REXX -- using character
strings for everything, COBOL -- traditionally using BCD arithmetic
unless one declared a variable usage as COMPutational, and maybe PL/1).
You then convert this to a human readable representation of binary
(using character 1 and 0 for each bit)... So far I understand it. But
then you feed these string representation of a binary number to a
function that treats it as a string representation of a DECIMAL number,
and converts said decimal back to an internal binary format which bears
no resemblence to the 0/1 bits you started with.

You can't do arithmetic with the result: Say 2 + 3 were the
originals...

2d => 0010b
3d => 0011b
+(in native binary)
5d => 0101b

but in your method, feeding back through int()

2d => 0010b => 10d (1010b)
3d => 0011b => 11d (1011b)
+ +
5d => 0101b !-> 21d (00010101b)

If the only purpose is to get a displayable binary value, leave the
result as a string and don't call int(). Actually, with leading 0s, that
int() call is probably interpreting the string as OCTAL, rather than
DECIMAL.
This is faster than my version (but if you are using Psyco for all the
tests, for small numbers my version is faster).
For moderate numbers, mine is using the, hopefully quite optimized
string formatting operations (which should be nearly as fast as doing
the same in C: sprintf(stringbuff, "%X", n);), and then doing hopefully
fast dictionary lookups to get the pieces.

-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Sep 4 '05 #6
Dennis Lee Bieber:
Yes, but only when ref-counts go to 0... it may be that this tight loop never allowed stuff to go to 0 ref-counts. It definitely never returned control, so besides eating memory that way, any events for the GUI framework were also not being handled and had to be queued.<
This memory allocation problem is present even without the loop. In
this other example if you keep cliking on the Go button, the memory
used keep growing:

from Tkinter import *
def dogo(): b.config(command=dogo)
root = Tk()
b = Button(root, text="Go", command=dogo)
b.pack()
root.mainloop()

with leading 0s, that int() call is probably interpreting the string as OCTAL, rather than DECIMAL.<
This can be fixed with a different dictionary that doesn't contain the
leading 0s, to be used just for the first (not the "-") nibble.

What is the real use case for this conversion?<


You are right, I'll remove the int conversion.

Thank you, a bear hug,
Bearophile

Sep 6 '05 #7
Bearophile>This can be fixed with a different dictionary that doesn't
contain the leading 0s,<

No other dict is necessary:

! _nibbles = {"0":"0000", "1":"0001", "2":"0010", "3":"0011",
! "4":"0100", "5":"0101", "6":"0110", "7":"0111",
! "8":"1000", "9":"1001", "A":"1010", "B":"1011",
! "C":"1100", "D":"1101", "E":"1110", "F":"1111",
! "-":"-"}
!
! def toBase2(number):
! """toBase2(number): given an int/long, converts it
! to a string containing the number in base 2."""
! # From a suggestion by Dennis Lee Bieber.
! if number == 0:
! return "0"
! result = [_nibbles[nibble] for nibble in "%X"%number]
! result[number<0] = result[number<0].lstrip("0")
! return "".join(result)
!
! for i in xrange(-20, 21):
! print toBase2(i)

Bye,
Bearophile

Sep 6 '05 #8
On 6 Sep 2005 06:01:40 -0700, be************@lycos.com declaimed the
following in comp.lang.python:

This memory allocation problem is present even without the loop. In
this other example if you keep cliking on the Go button, the memory
used keep growing:
No idea then -- I'd hope the .mainloop process wasn't that
inefficient to keep references to all historical states <G>
-- ================================================== ============ <
wl*****@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
================================================== ============ <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.netcom.com/> <

Sep 6 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
1460
by: Gitte Wange | last post by:
Hello, I'm trying to create an application that needs a Timer() to do various checks. My class has a self.timer = Timer(900, self.sendDNSRequest) The timer itself works fine but whenever I try...
7
4715
by: Steve M | last post by:
I'm trying to invoke a Java command-line program from my Python program on Windows XP. I cannot get the paths in one of the arguments to work right. The instructions for the program describe the...
8
1564
by: n3crius | last post by:
hi, i just got a web host with asp.net , seemed really cool. aspx with the c# or vb IN the actual main page run fine, but when i use codebehind and make another source file ( a .cs) to go with...
4
4969
by: Bit byte | last post by:
I have a project that I normally build (without problems) from the DevStudio IDE. However, I have embarked on automating all my builds (this test project being one of several). The project...
0
1348
by: hazz | last post by:
I want to load Service.exe.config into a DataGrid, change the timer interval value from 10000 to 555555, then update the original exe.config. The code below shows the code at step 1 and 2 before...
5
3383
by: Rajesh | last post by:
Hi, The '-I<path>' option adds the path to the list of directories that contains modules that can be included in a script. I can use it as "#!/ usr/bin/perl -I<path_to_my_modules>" thereby not...
13
4474
by: Chris Carlen | last post by:
Hi: Having completed enough serial driver code for a TMS320F2812 microcontroller to talk to a terminal, I am now trying different approaches to command interpretation. I have a very simple...
40
29301
by: =?Utf-8?B?Um9iZXJ0IEUuIEZsYWhlcnR5?= | last post by:
What is the C# command to wait for a specified period of time? I am writing a windows service that will process a file once it has beed created or changed. I'm using the fileSystemWatcher to...
4
3742
by: enggwaqas | last post by:
I have an Oracle stored procedure that takes approx 3 minutes to execute and I am using .net 2.0 data access provider for oracle. Now i want to cancel the execution of stored procedure from .net...
0
7226
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7125
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7328
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7388
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
7049
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
5631
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5055
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4709
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
3199
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.