如果print s
被print >>sys.stderr, s
替换,则效果会消失。
import random, sys, time
import threading
lock = threading.Lock()
def echo(s):
time.sleep(1e-3*random.random()) # instead of threading.Timer()
with lock:
print s
for c in 'abc':
threading.Thread(target=echo, args=(c,)).start()
# Run until empty line is found:
$ while ! python example.py 2>&1|tee out|grep '^$';do echo -n .;done;cat out
....................
b
c
a
输出不应包含空行,但确实如此。我知道print
不是线程安全的,但我认为锁应该有用。
我的机器:
$ python -mplatform
Linux-2.6.38-11-generic-x86_64-with-Ubuntu-11.04-natty
在py26,py27,pypy上打印额外的行。
py24,py25,py31,py32表现得如预期的那样(没有空行)。
print
无法解决问题后with lock:
print(s)
sys.stdout.flush()
更奇怪的是,普通sys.stdout.write()
不会产生带锁的空行:
with lock:
sys.stdout.write(s)
sys.stdout.write('\n') #NOTE: no .flush()
print
function按预期工作(没有空行)。
$ tox
答案 0 :(得分:4)
看看这个stackoverflow线程:How do I get a thread safe print in Python 2.6?。显然,打印到sout不是线程安全的。
如果打开详细线程,您可以更好地看到它:
threading.Thread(target=echo, args=(c,), verbose=True).start()
我得到这样的输出:
MainThread: <Thread(Thread-1, initial)>.start(): starting thread
Thread-1: <Thread(Thread-1, started 6204)>.__bootstrap(): thread started
MainThread: <Thread(Thread-2, initial)>.start(): starting thread
Thread-2: <Thread(Thread-2, started 3752)>.__bootstrap(): thread started
MainThread: <Thread(Thread-3, initial)>.start(): starting thread
Thread-3: <Thread(Thread-3, started 4412)>.__bootstrap(): thread started
MainThread: <Thread(Thread-2, started 3752)>.join(): waiting until thread stops
a
b
Thread-1: <Thread(Thread-1, started 6204)>.__bootstrap(): normal return
Thread-2: <Thread(Thread-2, started 3752)>.__bootstrap(): normal return
MainThread: <Thread(Thread-2, stopped 3752)>.join(): thread stopped
MainThread: <Thread(Thread-3, started 4412)>.join(): waiting until thread stops
Thread-3: <Thread(Thread-3, started 4412)>.__bootstrap(): normal return
MainThread: <Thread(Thread-3, stopped 4412)>.join(): thread stopped
c
在打印'c'字符之前,您可以看到线程3显示为完成。显然情况并非如此,因此这使我假设打印到控制台不是线程安全的。
然而,这并不能解释为什么打印到sys.stderr似乎能正常工作。
答案 1 :(得分:0)
因为先打印先写入标准输出文本,然后再写入结束字符串。伪代码解释:
def print(*args, **kwargs):
write_to_stdout(to_single_string(args))
write_to_stdout(end) # usually a newline "\n"
因此,在多线程处理中,两个线程的第一个字符串在第二个字符串之前执行,因此同时打印了两个换行符。但是,为什么行不在同一行上?我不知道。需要更深入地检查python打印的实现。