为什么使用线程的脚本偶尔会打印额外的行?
如果将 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 的行为符合预期(没有空行)。
变体
sys.stdout.flush()< /code>
print
后没有解决问题:带锁: 印刷) sys.stdout.flush()
更奇怪的是普通的
sys.stdout.write()
不会产生带锁的空行:带锁: sys.stdout.write(s) sys.stdout.write('\n') #注意:没有 .flush()
打印
函数 按预期工作(无空行)。
要重现下载文件并运行:
$ tox
If print s
is replaced by print >>sys.stderr, s
then the effect vanishes.
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()
Example
# Run until empty line is found:
$ while ! python example.py 2>&1|tee out|grep '^
Output
....................
b
c
a
The output should not contain empty lines, but it does. I understand that print
is not thread-safe, but I would've thought the lock should help.
The question is why this happens?
My machine:
$ python -mplatform
Linux-2.6.38-11-generic-x86_64-with-Ubuntu-11.04-natty
Extra lines are printed on py26, py27, pypy.
py24, py25, py31, py32 behave as expected (no empty lines).
Variations
-
sys.stdout.flush()
after the print
doesn't solve the problem:
with lock:
print(s)
sys.stdout.flush()
-
even more strange that ordinary sys.stdout.write()
doesn't produce empty lines with lock:
with lock:
sys.stdout.write(s)
sys.stdout.write('\n') #NOTE: no .flush()
-
print
function works as expected (no empty lines).
To reproduce download files and run:
$ tox
;do echo -n .;done;cat out
Output
The output should not contain empty lines, but it does. I understand that print
is not thread-safe, but I would've thought the lock should help.
The question is why this happens?
My machine:
Extra lines are printed on py26, py27, pypy.
py24, py25, py31, py32 behave as expected (no empty lines).
Variations
sys.stdout.flush()
after theprint
doesn't solve the problem:even more strange that ordinary
sys.stdout.write()
doesn't produce empty lines with lock:print
function works as expected (no empty lines).
To reproduce download files and run:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看看这个 stackoverflow 线程: 如何在 Python 2.6 中获得线程安全打印?。显然,打印到 sout 不是线程安全的。
如果您打开详细线程,您可以更好地看到这一点:
我得到如下输出:
您可以看到线程 3 在打印“c”字符之前显示为完成。显然情况并非如此,因此这使我假设打印到控制台不是线程安全的。
然而,这并不能解释为什么打印到 sys.stderr 似乎可以正常工作。
Take a look at this stackoverflow thread: How do I get a thread safe print in Python 2.6?. Apparently, printing to sout is not thread-safe.
If you turn on verbose threading, you can see this better:
I get output like this:
You can see that thread 3 is shown as finishing before printing the 'c' character. This clearly cannot be the case, so this leads me to assume that printing to the console is not thread-safe.
This, however, does not explain why printing to sys.stderr appears to work correctly.
因为 print 首先写入标准输出文本,然后结束字符串。伪代码解释:
因此,在多线程中,两个线程的第一个字符串在第二个线程之前执行,因此同时打印两个换行符。但为什么线不在同一线上呢?我不知道。需要更深入地检查 python print 的实现。
Because print write to stdout text first, then end string. Pseudo-code to explain:
so, in multithreading first string of both threads executes before second, so two newlines printed at the same time. But why lines don't on same line? I don't know. Needs to check realization of python print more deeply.