繁体   English   中英

Python线程与奇怪的输出错误

[英]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来执行输出; 要么
  • 你使用的是具有不同io结构的Python 3.x.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM