gpt4 book ai didi

python - 如何在 Python 2.6 中获得线程安全打印?

转载 作者:IT老高 更新时间:2023-10-28 20:31:43 26 4
gpt4 key购买 nike

根据 these,Python 中的

print 不是线程安全的articles .

后一篇文章中提供了 Python 3 解决方法。

如何在 Python 2.6 中获得线程安全的 print

最佳答案

有趣的问题——考虑到 print 语句中发生的所有事情,包括 softspace 属性的设置和检查,使其“线程安全”(意思是,实际上:一个正在打印的线程在打印换行符时只向另一个线程产生“标准输出的控制”,因此保证输出的每一整行都来自单个线程)有点挑战(通常的简单方法为了实际线程安全——委派一个单独的线程专门“拥有”和处理sys.stdout,通过Queue.Queue与其通信——并不是那么有用,因为问题是 不是 线程安全 [[即使使用普通的 print 也没有崩溃的风险,并且最终出现在标准输出上的字符正是那些被打印的字符]] 但需要在线程之间进行互斥以扩展操作范围)。

所以,我想我做到了……:

import random
import sys
import thread
import threading
import time

def wait():
time.sleep(random.random())
return 'W'

def targ():
for n in range(8):
wait()
print 'Thr', wait(), thread.get_ident(), wait(), 'at', wait(), n

tls = threading.local()

class ThreadSafeFile(object):
def __init__(self, f):
self.f = f
self.lock = threading.RLock()
self.nesting = 0

def _getlock(self):
self.lock.acquire()
self.nesting += 1

def _droplock(self):
nesting = self.nesting
self.nesting = 0
for i in range(nesting):
self.lock.release()

def __getattr__(self, name):
if name == 'softspace':
return tls.softspace
else:
raise AttributeError(name)

def __setattr__(self, name, value):
if name == 'softspace':
tls.softspace = value
else:
return object.__setattr__(self, name, value)

def write(self, data):
self._getlock()
self.f.write(data)
if data == '\n':
self._droplock()

# comment the following statement out to get guaranteed chaos;-)
sys.stdout = ThreadSafeFile(sys.stdout)

thrs = []
for i in range(8):
thrs.append(threading.Thread(target=targ))
print 'Starting'
for t in thrs:
t.start()
for t in thrs:
t.join()
print 'Done'

wait 的调用旨在保证在没有这种互斥保证(注释来源)的情况下混沌混合输出。 使用包装,即上面的代码与它看起来完全一样,以及(至少)Python 2.5 及更高版本(我相信这也可以在早期版本中运行,但我没有很容易检查)输出是:

Thr W -1340583936 W at W 0
Thr W -1340051456 W at W 0
Thr W -1338986496 W at W 0
Thr W -1341116416 W at W 0
Thr W -1337921536 W at W 0
Thr W -1341648896 W at W 0
Thr W -1338454016 W at W 0
Thr W -1339518976 W at W 0
Thr W -1340583936 W at W 1
Thr W -1340051456 W at W 1
Thr W -1338986496 W at W 1
...more of the same...

“序列化”效应(即线程看起来像上面那样“很好地循环”)是一个副作用,即成为当前正在打印的线程比其他线程慢很多(所有那些等待!-)。注释掉wait中的time.sleep,输出改为

Thr W -1341648896 W at W 0
Thr W -1341116416 W at W 0
Thr W -1341648896 W at W 1
Thr W -1340583936 W at W 0
Thr W -1340051456 W at W 0
Thr W -1341116416 W at W 1
Thr W -1341116416 W at W 2
Thr W -1338986496 W at W 0
...more of the same...

即更典型的“多线程输出”...除了保证输出中的每一行完全来自一个线程。

当然,执行此操作的线程,例如 print 'ciao', 将保留标准输出的“所有权”,直到它最终执行没有尾随的打印逗号,而其他想要打印的线程可能会休眠很长一段时间(否则如何保证输出中的每一行都来自单个线程?嗯,一种架构是将部分行累积到线程本地存储而不是实际写入将它们输出到标准输出,并且只在收到 \n... 时才进行写入,以便与 softspace 设置正确交错,我担心,但可能是可行的)。

关于python - 如何在 Python 2.6 中获得线程安全打印?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3029816/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com