jfs*_*jfs 7 python io multithreading buffering
如果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 Code Online (Sandbox Code Playgroud)
# Run until empty line is found:
$ while ! python example.py 2>&1|tee out|grep '^$';do echo -n .;done;cat out
Run Code Online (Sandbox Code Playgroud)
....................
b
c
a
Run Code Online (Sandbox Code Playgroud)
输出不应包含空行,但确实如此.我知道这print不是线程安全的,但我认为锁应该有所帮助.
我的机器:
$ python -mplatform
Linux-2.6.38-11-generic-x86_64-with-Ubuntu-11.04-natty
Run Code Online (Sandbox Code Playgroud)
额外的线条印在py26,py27,pypy上.
py24,py25,py31,py32表现得如预期的那样(没有空行).
sys.stdout.flush()之后print没有解决问题:
with lock:
print(s)
sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)更奇怪的是普通sys.stdout.write()不会产生带锁的空行:
with lock:
sys.stdout.write(s)
sys.stdout.write('\n') #NOTE: no .flush()
Run Code Online (Sandbox Code Playgroud)print 函数按预期工作(没有空行).
$ tox
Run Code Online (Sandbox Code Playgroud)
小智 4
看看这个 stackoverflow 线程:How do I get a thread safe print in Python 2.6? 。显然,打印到 sout 不是线程安全的。
如果您打开详细线程,您可以更好地看到这一点:
threading.Thread(target=echo, args=(c,), verbose=True).start()
Run Code Online (Sandbox Code Playgroud)
我得到这样的输出:
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
Run Code Online (Sandbox Code Playgroud)
您可以看到线程 3 显示为在打印“c”字符之前完成。显然情况并非如此,因此这使我假设打印到控制台不是线程安全的。
然而,这并不能解释为什么打印到 sys.stderr 似乎可以正常工作。