[英]Python threading with strange output errors
我是新手一般的线程,并且一直在玩弄不同的想法让我脚踏实地。 但是,我遇到了一些我不确定如何解释的事情。 这是代码:
import threading, datetime
class ThreadClass(threading.Thread):
def run(self):
for _ in range(3):
now = datetime.datetime.now()
print "%s: %s" %(self.getName(), now)
for i in range(2):
t = ThreadClass()
t.start()
该程序正是我想要它做的,但是,输出中有一些随机错误。
Thread-1: 2016-10-12 17:34:23.012462
Thread-1: 2016-10-12 17:34:23.012802
Thread-2: 2016-10-12 17:34:23.013025
Thread-2: 2016-10-12 17:34:23.013108
Thread-2: 2016-10-12 17:34:23.013225
Thread-1: 2016-10-12 17:34:23.013252
错误是相对一致的(即输出中显示相同的空格和新行,只是在不同的地方)。 我怀疑它与几乎同时写入输出流的线程有关,但是在这个特定的运行中,当Thread-2运行时会发生两个错误。
任何帮助描述为什么会出现这个问题非常感谢!
我在Ubuntu 14.04(双核CPU)上使用Python 2.7运行此代码,如果这会有所不同。
作为Joseph回复的补充,你可以使用Semaphore
from threading import Semaphore
writeLock = Semaphore(value = 1)
...
当您要在线程中打印时:
writeLock.acquire()
print ("%s: %s" %(self.getName(), now))
writeLock.release()
writeLock确保在release()之前的任何一个时刻只能打印一个线程。
想象一下信号量是“苍蝇之王”中的海螺,只有得到它的人才能说话。 当第一个发言者结束时,他将它交给下一个发言者。
您正在寻找记录模块:
15.7.9。 线程安全
日志记录模块旨在是线程安全的,无需客户端进行任何特殊工作。 它通过使用线程锁来实现这一点; 有一个锁可以序列化对模块共享数据的访问,每个处理程序还会创建一个锁,以序列化对其底层I / O的访问。
这是一个例子:
FORMAT = '%(threadName)s %(asctime)s'
logging.basicConfig(format=FORMAT, level=logging.DEBUG) # "level" default is to only print WARN and above.
logger = logging.getLogger('MyThreadClass')
logger.debug('')
你的部分问题是为什么会发生这种情况? 这是一个很好的问题,因为你会在输出中注意到有一个完全虚假的空间,这两个线程都没有真正尝试打印
Thread-1: 2016-10-12 17:34:23.012802
Thread-2: 2016-10-12 17:34:23.013025
^
那是怎么到达那里的? 没有你的线程试图打印它! 它是由于Python 2.x中的print
语句实现软间距的方式 。
例如......当你执行print 1,
你会在stdout
收到
1 # there is no space after that 1 yet!
然后后续print 2
将导致插入空格以给出最终输出:
1 2
发生的事情是print <something>,
语句被编译到字节码操作PRINT_ITEM
。 PRINT_ITEM
的实现:
PRINT_ITEM
将其标记为需要打印软空间; 还有另一个字节码操作PRINT_NEWLINE
,它打印一个新行并清除流上的任何软空间标记。
现在在您的代码中,每个线程将执行以下操作:
print "%s: %s" %(self.getName(), now)
这被编译为:
PRINT_ITEM # print the top of the stack
PRINT_NEWLINE # print a new line
因此,线程交互可能意味着:
Thread-1
可以执行PRINT_ITEM
并将流标记为需要下一个PRINT_ITEM的PRINT_ITEM
; Thread-2
可以开始PRINT_ITEM
,并且看到流需要一个软空间; Thread-1
现在打印一个新行; Thread-2
现在打印该空间及其项目; 请注意,如果出现以下情况不会发生此错
sys.stdout.write
来执行输出; 要么
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.