Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why does this code crash python?

4 views
Skip to first unread message

Myt...@gmail.com

unread,
Nov 11, 2006, 2:17:06 PM11/11/06
to
I am trying to make a program that will basically simulate a chess
clock in python. To do this I have two threads running, one that
updates the currently running clock, and one that watches for a
keypress. I am using the effbot Console module, and that is where I get
the events for the keypresses. But when I press space it crashes
shortly after. The program stops, the Console closes, and windows says
that the program pythonw.exe has had an unexpected reason to shut down.
I am using python2.5.

If there is a simpler way to do this ( I tried without threads but had
some problems with the Console module giving me input right and still
letting the timer display count down ) I would like to know about it. I
am not a very good programmer, and don't have much experience with
python

note: A chess clock is two timers that count down from a set time, and
when you start one of the timer the other stops.

Code below:

import time
import Console
from threading import Thread

c = Console.getconsole()

turn = 0

class timer (Thread):
def run ( self ):
global turn
oldTime = [time.time(), time.time()]
timeLeft = [260, 260]

go = True
while go:
newTime = time.time()
timeLeft[turn] -= newTime - oldTime[turn]
oldTime[turn] = newTime
minutes = [str(int(timeLeft[0]//60)),
str(int(timeLeft[1]//60))]
seconds = [str(timeLeft[0]%60)[0:5],
str(timeLeft[1]%60)[0:5]]

if float(seconds[0]) < 10: seconds[0] = '0' +
seconds[0][:-1]
if float(seconds[1]) < 10: seconds[1] = '0' +
seconds[1][:-1]

c.text(3,3,minutes[0] + ':' + seconds[0])
c.text(12,3,minutes[1] + ':' + seconds[1])

time.sleep(.1)

class eventMonitor (Thread):
def run ( self ):
global turn
go = True
while go:
event = c.peek()
if event != None:
c.get()
if event.type == 'KeyPress':
if event.keycode == 32:
if turn == 1: turn = 0
if turn == 0: turn = 1
c.text(10,20,'1')

timer().start()
eventMonitor().start()

Irmen de Jong

unread,
Nov 11, 2006, 2:28:41 PM11/11/06
to
Myt...@gmail.com wrote:
> I am trying to make a program that will basically simulate a chess
> clock in python. To do this I have two threads running, one that
> updates the currently running clock, and one that watches for a
> keypress. I am using the effbot Console module, and that is where I get
> the events for the keypresses. But when I press space it crashes
> shortly after. The program stops, the Console closes, and windows says
> that the program pythonw.exe has had an unexpected reason to shut down.
> I am using python2.5.

Try not (re)using an object created in a certain thread in another thread.
You're creating a console object "c" and use it in both threads.

Try creating the console object for each thread by itself,
i.e. remove the global "c = Console.getconsole()" and replace
it by a getconsole() inside each thread class.

I don't have the Console module so I don't know if it fixes things
for you, but give it a try :)

--Irmen

Myt...@gmail.com

unread,
Nov 11, 2006, 3:28:05 PM11/11/06
to
On Nov 11, 11:28 am, Irmen de Jong <irmen.NOS...@xs4all.nl> wrote:
> You're creating a console object "c" and use it in both threads.
>
> Try creating the console object for each thread by itself,
> i.e. remove the global "c = Console.getconsole()" and replace
> it by a getconsole() inside each thread class.
>
> I don't have the Console module so I don't know if it fixes things
> for you, but give it a try :)

Well, I tried that, and it did something. It made it so the space bar
switched the clock once, but not a second time. And it still crashed,
but not always at the same time, sometimes it would do it the second
time I hit the space bar, sometimes before I hit it the first time, but
always when i did something that would generate a Console event (moving
the mouse or something). So, I thought it had something to do with
Console not working well with threads, so I took it completely out of
threads and had just the event checking loop run by itself, and it
still crashed. So apparently I am using the Console events wrong. I am
going to try and find some examples online on how to watch for events
with it, but if worse comes to worse I can try and use keyboard hooks,
I've looked at those before, and they might work better.

--Mythmon

Sandy

unread,
Nov 11, 2006, 5:46:38 PM11/11/06
to
In article <1163276885.6...@h54g2000cwb.googlegroups.com>,
Myt...@gmail.com wrote

>Well, I tried that, and it did something. It made it so the space bar
>switched the clock once, but not a second time. And it still crashed,
>but not always at the same time, sometimes it would do it the second
>time I hit the space bar, sometimes before I hit it the first time, but
>always when i did something that would generate a Console event (moving
>the mouse or something). So, I thought it had something to do with
>Console not working well with threads, so I took it completely out of
>threads and had just the event checking loop run by itself, and it
>still crashed. So apparently I am using the Console events wrong. I am
>going to try and find some examples online on how to watch for events
>with it, but if worse comes to worse I can try and use keyboard hooks,
>I've looked at those before, and they might work better.

Dear Pythonauts,

I usually lurk on the comp.lang.python newsgroup. I'm not an expert
in the slightest, but I have had a growing feeling that there's
something definitely lacking in the concurrency aspects of Python. It
is the same problem with Java. Forgive me if I don't know the right
vocabulary, but Python concurrency seems to be exposed at too "low a
level". It's like assembler: it's all _possible_ to implement, but in
practise it's very complicated and fragile, glitchy, and really
difficult to extend. Like programming in Dartmouth BASIC with just
conditionals and "goto" instructions, before structured programming.

A higher-level system of concurrency, not based on monitors and
locks and great programmer discipline, will ultimately require making
"Python 3000" a reality.

In the meantime, is there anywhere, or any thing, that discusses the
various concurrency options related to Python? There's Stackless Python
(which I can't make head or tail of; I have been unable to find any
lucid overview, or genuine explanation of the purpose of the design.) I
know that there's a package for an Erlang system for Python, somewhere
("Parnassus" probably). There's probably a Py-CSP somewhere too. Lots
of trees, but where's the Wood?

Where are concurrency/distributed models compared and discussed?

With kind regards,

Sandy
--
Alexander Anderson <junk.r...@alma-services.abel.co.uk>
(Yorkshire, England)

Where there is no vision, the people perish.

Fredrik Lundh

unread,
Nov 11, 2006, 6:18:28 PM11/11/06
to pytho...@python.org
Sandy wrote:

> I usually lurk on the comp.lang.python newsgroup. I'm not an expert
> in the slightest, but I have had a growing feeling that there's
> something definitely lacking in the concurrency aspects of Python.

the culprit in this case appears to be Microsoft's console library,
though. I'm pretty sure that's not written in Python.

</F>

Message has been deleted

Myt...@gmail.com

unread,
Nov 11, 2006, 7:48:06 PM11/11/06
to

On Nov 11, 3:23 pm, Dennis Lee Bieber <wlfr...@ix.netcom.com> wrote:
> I have no knowledge of Console, but under Windows I was able to hack
> this (see bottom of post) together using only one non-portable library
> -- msvcrt. Oh, and an ActiveState 2.4 build. I'm not touching 2.5 until
> a lot of 3rd party stuff is rebuilt and installers are available.
>

And here I am thinking this was going to be an easy project. I haven't
had a chance to work on this since my last message, but that example
should be a good thing, since now i have an example of how threads
/should/ be done. I was pretty much just guessing so far.

>
> > newTime = time.time()
> > timeLeft[turn] -= newTime - oldTime[turn] I'd duplicated this form, but it is wrong... when the clock swaps it
> will immediately decrement the current clock by the difference since it
> was last updated!


>
> > if float(seconds[0]) < 10: seconds[0] = '0' +
> > seconds[0][:-1]
> > if float(seconds[1]) < 10: seconds[1] = '0' +

> > seconds[1][:-1] I've not handled leading 0s on the seconds field (I tried, but can't
> figure out how to specify zero-filled field width for floats -- works
> for integers)
>

I ran into the same problem, thats why I did it the way I did, instead
of continuing to wrestle with python's string formatting.

> > go = True
> > while go: Why define "go" when it never changes

Whenever I make infinite loops, I put in a control variable so I could
stop it if I want, which I was planning on doing, when the time runs
out or something like that.


>
> Note that I lock access to timeLeft and side to ensure they don't
> change in the middle of access; may not have been critical, but why risk
> it (and if the code gets expanded so the changes take more time -- or
> multiple look-ups using side).
>
> getch() doesn't seem to return a value for <ctrl-c>, so I used
> <ctrl-z>
>
> Uh, it also updates the time with an invalid negative before it
> exits <G>

Now to see if I can get this to work for my self with an example. This
is more a learning project than something that has to be done.

Martin Blume

unread,
Nov 12, 2006, 7:40:58 AM11/12/06
to
<Myt...@gmail.com> schrieb
> I am trying to make a program that will basically simulate
> a chess clock in python. ...
> ... it crashes shortly after.

Can't help you on why it crashes, but

>
> class eventMonitor (Thread):
> def run ( self ):

> [snipped]


> if event.keycode == 32:
> if turn == 1: turn = 0
> if turn == 0: turn = 1
>

looks wrong to me. This is supposed to switch between the
players (0 and 1), but the first if changes turn to 0, the
second changes it immediately back to 1.

I'd do:


if turn == 1: turn = 0

else: turn = 1

HTH
Martin


Paul Boddie

unread,
Nov 12, 2006, 9:45:01 AM11/12/06
to
Sandy wrote:
>
> A higher-level system of concurrency, not based on monitors and
> locks and great programmer discipline, will ultimately require making
> "Python 3000" a reality.

It would surprise me if Python 3000 introduced anything substantially
more than what Python 2.x provides in the area of concurrency.

> In the meantime, is there anywhere, or any thing, that discusses the
> various concurrency options related to Python? There's Stackless Python
> (which I can't make head or tail of; I have been unable to find any
> lucid overview, or genuine explanation of the purpose of the design.)

What about this introduction...?

http://members.verizon.net/olsongt/stackless/why_stackless.html

> I know that there's a package for an Erlang system for Python, somewhere
> ("Parnassus" probably). There's probably a Py-CSP somewhere too. Lots
> of trees, but where's the Wood?

Here are some fairly similar projects in Python:

http://kamaelia.sourceforge.net/
- a way of making general concurrency easy to work with, and fun

http://candygram.sourceforge.net/
- a Python implementation of Erlang concurrency primitives

http://www.python.org/pypi/parallel
- process forking and channel-based communication (using pickles)

> Where are concurrency/distributed models compared and discussed?

In the following article and comments there are some opinions expressed
on Python concurrency (along with the usual dose of Ruby vapourware
promotion):

http://www.oreillynet.com/onlamp/blog/2005/10/does_python_have_a_concurrency.html

Meanwhile, the topic has been discussed on python-dev:

http://mail.python.org/pipermail/python-dev/2005-September/056801.html

That discussion led to a description of something which isn't so far
from parallel/pprocess, at least:

http://mail.python.org/pipermail/python-dev/2005-September/056829.html

Other searching yielded this interesting paper about PyPy and "hardware
transactional memory":

http://portal.acm.org/citation.cfm?id=1176617.1176758&coll=ACM&dl=ACM&type=series&idx=1176617&part=Proceedings&WantType=Proceedings&title=Conference%20on%20Object%20Oriented%20Programming%20Systems%20Languages%20and%20Applications&CFID=15151515&CFTOKEN=6184618

Paul

Scott David Daniels

unread,
Nov 12, 2006, 8:14:51 PM11/12/06
to
Myt...@gmail.com wrote:
>...

>>> if float(seconds[0]) < 10: seconds[0] = '0' +
>>> seconds[0][:-1]
>>> if float(seconds[1]) < 10: seconds[1] = '0' +
>>> seconds[1][:-1] I've not handled leading 0s on the seconds field (I tried, but can't
>> figure out how to specify zero-filled field width for floats -- works
>> for integers)
>
> I ran into the same problem, thats why I did it the way I did, instead
> of continuing to wrestle with python's string formatting.

For this portion, you could quite simply:

totalsecs = int(whatever)
print '%02d:%02d' % divmod(totalsecs, 60)

Or, depending on your leading zero requirements:

totalsecs = int(whatever)
print '%2d:%02d' % divmod(totalsecs, 60)

--Scott David Daniels
scott....@acm.org

Michael

unread,
Nov 17, 2006, 6:43:46 PM11/17/06
to
Sandy wrote:
...

> Lots of trees, but where's the Wood?
>
> Where are concurrency/distributed models compared and discussed?


I don't know about wood, but you can find a shrubbery[*] called Kamaelia
sitting here:

* http://kamaelia.sourceforge.net/Home

A basic (albeit now aging) tutorial as to how to take some existing code and
create components which can be used is here:
*
http://kamaelia.sourceforge.net/cgi-bin/blog/blog.cgi?rm=viewpost&nodeid=1113495151

Perhaps usefully, there's an overview of Kamaelia in this whitepaper:
* http://www.bbc.co.uk/rd/pubs/whp/whp113.shtml

It does miss out work from the past 18 months work since it was written
though.

Also, every single example you see here:
* http://kamaelia.sourceforge.net/Cookbook.html

Is rather heavily parallel, except we just call our units of execution
components, components then talk in a CSP style fashion. The problem
you've *REALLY* got is making things accessible to the average developer.

That's the target audience for Kamaelia. ( If it doesn't work for that kind
of person, it's a conceptual bug in the system. )

As a result we normally refer to components being really simple,
communicating with the outside world via inboxes and outboxes (think
a person at a desk with some in-trays and out-trays).

Why? Because this is directly analogous to the ideas in both CSP *and* Unix
pipelines - the latter has been long understood by unix people as a way of
making it easier to build systems, the former understood largely by people
interested in parallelism as a good mechanism.

It also provices a nice route for development of new components - you
simply solve the core of the problem you wanted to solve, and then
remove the inputs back to inboxes and remove outputs back to outboxes.
It doesn't work for every class of problem, but does for a suprising
number.

We're in the process of revamping the website at the moment (it's November).
But for the moment, a simple tutorial on how the core concurrency tools in
Kamaelia fundamentally work is here:
* http://kamaelia.sourceforge.net/MiniAxon/

(The tutorial was originally written for a pre-university who'd learnt
python the previous week)

One interesting fact though - we have an application for collaborative
whiteboarding where each whiteboard is both a client & server, and they
can form a collaboration tree - whereby everything scribbled and said (each
whiteboard contains an audio mixer) is distributed to everyone connected in
a P2P like fashion. It's a classic example of a desktop application with a
small twist, and was written because we needed it.

The reason it's interesting is because it's highly parallel, with around
70 active components normally. *IF* the baseclass was changed to put
the generators in seperate threads, and ran under a Python VM that could
actually make the threads utilise seperate CPU's effectively (as allegedly
the IronPython VM does), then you'd be able to utilise a 60, 70 odd
multicore CPU with no change to the application code.

It's a nice example of a real world application written to solve a specific
need (we split the team multisite and needed an audio & scribbling based)
collaboration tool which is able to work effectively on existing hardware
systems, and *SHOULD* be trivially scalable to massively multicore systems
as VMs and CPUs become available, with no real change to the application
code. (Small change to Axon - our concurrency mechanism would be needed as
noted above. Obviously at the moment that change makes no sense to us)

It's also interesting because it was simpler to write due to the way we
make concurrency available (by thinking in terms of components that form
pipelines & graphlines), rather than despite using concurrency. (The initial
version took around 3 days)

If you want more detail on the whiteboard, there's been a tutorial in the
past month's Linux Format (ie December issue).

If you're interested in discussing anything concurrency related, and need a
forum to do so, you're more than welcome to use the Kamaelia mailing list
for doing so.

Kamaelia's hardest core goal is to make concurrency actually USEFUL for the
average developer. (though we tend to target maintenance over initial
development - which doesn't always makes life easier initially) That said,
we seem to be getting somewhere.

> There's Stackless Python (which I can't make head or tail of; I have been
> unable to find any lucid overview,

Finally, if the descriptions you find on the Kamaelia website don't make
sense to you, PLEASE tell us. I consider that as much of a bug as anything
else. (and we can't know that without being told)

Regards,


Michael.
--
Kamaelia Project Lead/Dust Puppy
http://kamaelia.sourceforge.net/Home
http://yeoldeclue.com/blog

[*] (yes, it's a deliberate mispelling of Camellia, which is a shrubbery,
rather than a backronym)

Michael

unread,
Nov 17, 2006, 7:43:46 PM11/17/06
to
The reason for your problem is that, at it's core, it's not threadsafe - you
have a shared data value that 2 distinct things are trying to update.

Myt...@gmail.com wrote:
...
> from threading import Thread

The following value is updated by 2 things trying to run in parallel.

> c = Console.getconsole()

The following value is used for communications.

> turn = 0


> class timer (Thread):
> def run ( self ):
> global turn

....


> go = True
> while go:
> newTime = time.time()
> timeLeft[turn] -= newTime - oldTime[turn]
> oldTime[turn] = newTime

value that "turn" relates to here is merely read. On the surface this looks
safe, but if turn changes in value between any of these 3 "reads" of the
value of "turn", then it will go wrong.

> c.text(3,3,minutes[0] + ':' + seconds[0])
> c.text(12,3,minutes[1] + ':' + seconds[1])

c gets updated here.

> class eventMonitor (Thread):
> def run ( self ):
> global turn

Shared data, but this is the only writer to this value.

> go = True
> while go:
> event = c.peek()
> if event != None:
> c.get()

... (turn gets updated here as well, which can cause a race hazard in timer)
> c.text(10,20,'1')

c effectively changes in value here as well.

> timer().start()
> eventMonitor().start()

Now you *could* introduce locks into this if you wanted. The alternative
approach is to recognise that the real reason you're hitting problems is
because you're using shared data, and that an alternative is to send
messages between the things you're using.

ie collect events from the keyboard,
send them to something handling the logic,
have that send a message (as you essentially do with "turn" above) to the
timer logic,
and then have that send a message to the display.

That way, since you have explicit hand off of data you don't run the risk of
your code crashing. (you also avoid a few other classes of problems :)

The way this would work with Kamaelia (given I've just posted elsewhere in
the thread about that) is you could build a simple pipeline as follows:

Pipeline( KeyEvent(key_events = { pygame.K_SPACE: ("SPACE", "outbox")} ),
ChessTurnLogic(),
TimerLogic(),
Ticker(background_colour=(128,48,128),
render_left = 1,
render_top = 1,
render_right = 600,
render_bottom = 200,
position = (100, 300),
)
).run()

This uses pygame for the display instead of the console which you're using.
It takes keypresses and turns them into a message to trigger the chess turn
logic to emit whose turn it is.

This then feeds into somethin that manages the timer logic - which in this
case emits a message (to be displayed by the ticker) about whose just
finished their turn, and how much time they spent on their turn.

KeyEvent and Ticker are pre-existing components.

The ChessTurnLogic looks like this:

class ChessTurnLogic(Axon.Component.component):
def main(self):
myturn, notmyturn = "white", "black"
self.send(myturn, "outbox")
while 1:
while self.dataReady("inbox"):
self.recv("inbox")
myturn, notmyturn = notmyturn, myturn
self.send(myturn, "outbox")
if not self.anyReady():
self.pause()
yield 1


The Timer Logic looks like this:

class TimerLogic(Axon.Component.component):
def main(self):
times_info = {}
player = None
while 1:
while self.dataReady("inbox"):
new_player = self.recv("inbox")
now = time.time()

if player is not None:
(total, last) = times_info[player]
total = total + (now - last)
times_info[player] = (total, now)
self.send(player + " " + str(total) + "\n\n", "outbox")

player = new_player
try:
(total, last) = times_info[player]
times_info[player] = (total, now)
except KeyError:
times_info[player] = (0, now)

if not self.anyReady():
self.pause()

yield 1

There's probably shorter ways of dealing with the timer logic, but it'll
also work for a draughts (checkers) logic component:

class DraughtsTurnLogic(Axon.Component.component):
def main(self):
myturn, notmyturn = "black", "white"
self.send(myturn, "outbox")
while 1:
while self.dataReady("inbox"):
self.recv("inbox")
myturn, notmyturn = notmyturn, myturn
self.send(myturn, "outbox")
if not self.anyReady():
self.pause()
yield 1

Or indeed a game where there are more than 2 players. (Which is a nice
sideeffect of decoupling your code like this)

The full thing including imports looks like this for reference:

#!/usr/bin/python

import Axon
import time
import pygame
from Kamaelia.Chassis.Pipeline import Pipeline
from Kamaelia.UI.Pygame.Ticker import Ticker
from Kamaelia.UI.Pygame.KeyEvent import KeyEvent

class ChessTurnLogic(Axon.Component.component):
def main(self):
myturn, notmyturn = "white", "black"
self.send(myturn, "outbox")
while 1:
while self.dataReady("inbox"):
self.recv("inbox")
myturn, notmyturn = notmyturn, myturn
self.send(myturn, "outbox")
if not self.anyReady():
self.pause()
yield 1

class TimerLogic(Axon.Component.component):
def main(self):
times_info = {}
player = None
while 1:
while self.dataReady("inbox"):
new_player = self.recv("inbox")
now = time.time()

if player is not None:
(total, last) = times_info[player]
total = total + (now - last)
times_info[player] = (total, now)
self.send(player + " " + str(total) + "\n\n", "outbox")

player = new_player
try:
(total, last) = times_info[player]
times_info[player] = (total, now)
except KeyError:
times_info[player] = (0, now)

if not self.anyReady():
self.pause()

yield 1

Pipeline( KeyEvent(key_events = { pygame.K_SPACE: ("SPACE", "outbox")} ),
ChessTurnLogic(),
TimerLogic(),
Ticker(background_colour=(128,48,128),
render_left = 1,
render_top = 1,
render_right = 600,
render_bottom = 200,
position = (100, 300),
)
).run()

(I've tested the above code BTW. It's not pretty, but it works :).
Prettiness could be added in all sorts of ways though :-)

0 new messages