issues with doctest and threads
Tim Peters
tim.peters at gmail.com
Mon Aug 8 19:17:10 EDT 2005
[Michele Simionato]
> I am getting a strange error with this script:
>
> $ cat doctest-threads.py
> """
> >>> import time, threading
> >>> def example():
> ... thread.out = []
> ... while thread.running:
> ... time.sleep(.01)
> ... thread.out.append(".")
> >>> thread = threading.Thread(None, example)
> >>> thread.running = True; thread.start()
> >>> time.sleep(.1)
> >>> thread.running = False
> >>> print thread.out
> ['.', '.', '.', '.', '.', '.', '.', '.', '.']
> """
>
> if __name__ == "__main__":
> import doctest; doctest.testmod()
>
> $ python doctest-threads.py
> Exception in thread Thread-1:
> Traceback (most recent call last):
> File "/usr/lib/python2.4/threading.py", line 442, in __bootstrap
> self.run()
> File "/usr/lib/python2.4/threading.py", line 422, in run
> self.__target(*self.__args, **self.__kwargs)
> File "<doctest __main__[1]>", line 5, in example
> NameError: global name 'thread' is not defined
It looks like pure thread-race accident to me. The main program does
nothing to guarantee that the thread is finished before it prints
`thread.out`, neither anything to guarantee that Python doesn't exit
while the thread is still running. Stuff, e.g., a time.sleep(5) after
"thread.running = False", and it's much more likely to work the way
you intended (but still not guaranteed).
A guarantee requires explicit synchronization; adding
>>> thread.join()
after "thread.running = False" should be sufficient. That ensures two things:
1. The `example` thread is done before thread.out gets printed.
2. The *main* thread doesn't exit (and Python doesn't start tearing itself
down) while the `example` thread is still running.
The exact output depends on OS scheduling accidents, but I expect
you'll see 10 dots most often.
BTW, trying to coordinate threads with sleep() calls is usually a Bad
Idea; you can't generally expect more from an OS than that it will
treat sleep's argument as a lower bound on the elapsed time the
sleeper actually yields the CPU.
More information about the Python-list
mailing list