简体   繁体   English

Python线程与奇怪的输出错误

[英]Python threading with strange output errors

I am new to threading in general and have been playing around with different ideas to get my feet under me. 我是新手一般的线程,并且一直在玩弄不同的想法让我脚踏实地。 However, I came across something I am not sure how to explain. 但是,我遇到了一些我不确定如何解释的事情。 Here is the code: 这是代码:

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()

The program does exactly what I wanted it to do, however, the output has some random errors in it. 该程序正是我想要它做的,但是,输出中有一些随机错误。

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

The errors are relatively consistent (ie the same space and new line show up in the output, just in different places). 错误是相对一致的(即输出中显示相同的空格和新行,只是在不同的地方)。 I suspect it has something to do with the threads trying to write to the output stream at about the same time, but in this particular run both errors occur when Thread-2 is running. 我怀疑它与几乎同时写入输出流的线程有关,但是在这个特定的运行中,当Thread-2运行时会发生两个错误。

Any assistance in describe why this issue is occuring is greatly appreciated! 任何帮助描述为什么会出现这个问题非常感谢!

I am running this code with Python 2.7 on Ubuntu 14.04 (dual-core CPU), if that would make any difference. 我在Ubuntu 14.04(双核CPU)上使用Python 2.7运行此代码,如果这会有所不同。

Complement to Joseph's reply, you can use Semaphore 作为Joseph回复的补充,你可以使用Semaphore

from threading import Semaphore
writeLock = Semaphore(value = 1)

... ...

When you are about to print in the thread: 当您要在线程中打印时:

writeLock.acquire()
print ("%s: %s" %(self.getName(), now))
writeLock.release()

writeLock makes sure only one thread can print at any single moment until release(). writeLock确保在release()之前的任何一个时刻只能打印一个线程。

Imagine Semaphore as the conch in the "Lord of the flies", only the one who gets it can speak. 想象一下信号量是“苍蝇之王”中的海螺,只有得到它的人才能说话。 When the first speaker finishes, he gives it to the next speaker. 当第一个发言者结束时,他将它交给下一个发言者。

You're looking for the logging module: 您正在寻找记录模块:

15.7.9. 15.7.9。 Thread Safety 线程安全

The logging module is intended to be thread-safe without any special work needing to be done by its clients. 日志记录模块旨在是线程安全的,无需客户端进行任何特殊工作。 It achieves this though using threading locks; 它通过使用线程锁来实现这一点; there is one lock to serialize access to the module's shared data, and each handler also creates a lock to serialize access to its underlying I/O. 有一个锁可以序列化对模块共享数据的访问,每个处理程序还会创建一个锁,以序列化对其底层I / O的访问。

Here is an example: 这是一个例子:

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('')

Part of your question is why is this occurring? 你的部分问题是为什么会发生这种情况? And its a good question as you'll notice in your output there is a completely spurious space that neither of the threads actually tried to print 这是一个很好的问题,因为你会在输出中注意到有一个完全虚假的空间,这两个线程都没有真正尝试打印

Thread-1: 2016-10-12 17:34:23.012802
 Thread-2: 2016-10-12 17:34:23.013025
^

How did that get there? 那是怎么到达那里的? None of your threads tried to print it! 没有你的线程试图打印它! Its due to the way the print statement in Python 2.x implements soft spacing . 它是由于Python 2.x中的print语句实现软间距的方式

For example ... when you execute print 1, you receive on stdout 例如......当你执行print 1,你会在stdout收到

1              # there is no space after that 1 yet!

Then a subsequent print 2 will cause a space to be inserted to give a final output of: 然后后续print 2将导致插入空格以给出最终输出:

1 2

What is happening is that a print <something>, statement gets compiled to the bytecode operation PRINT_ITEM . 发生的事情是print <something>,语句被编译到字节码操作PRINT_ITEM The implementation of PRINT_ITEM : PRINT_ITEM的实现:

  • checks the output stream to see if the last PRINT_ITEM to this stream marked it as needing a soft space printed; 检查输出流以查看此流的最后一个PRINT_ITEM将其标记为需要打印软空间;
  • if it does, print a " "; 如果是的话,打印一个“”;
  • then print our item and remark the stream as needing another soft space. 然后打印我们的项目并将流注释为需要另一个软空间。

And there is another bytecode operation PRINT_NEWLINE which prints a new line and clears any soft space marker on the stream. 还有另一个字节码操作PRINT_NEWLINE ,它打印一个新行并清除流上的任何软空间标记。

Now in your code, each thread will do the following: 现在在您的代码中,每个线程将执行以下操作:

print "%s: %s" %(self.getName(), now)

This gets compiled to: 这被编译为:

PRINT_ITEM          # print the top of the stack
PRINT_NEWLINE       # print a new line

Thus, thread interaction can mean that: 因此,线程交互可能意味着:

  • Thread-1 can perform PRINT_ITEM and mark the stream as needing a softspace for the next PRINT_ITEM ; Thread-1可以执行PRINT_ITEM并将流标记为需要下一个PRINT_ITEM的PRINT_ITEM ;
  • Thread-2 can begin PRINT_ITEM , and see the stream needs a soft space; Thread-2可以开始PRINT_ITEM ,并且看到流需要一个软空间;
  • Thread-1 now prints a new line; Thread-1现在打印一个新行;
  • Thread-2 now prints that space and its item; Thread-2现在打印该空间及其项目;

Note that this error would not occur if: 请注意,如果出现以下情况不会发生此错

  • you used sys.stdout.write to perform your output; 你使用sys.stdout.write来执行输出; or 要么
  • you were using Python 3.x which has a different io structure 你使用的是具有不同io结构的Python 3.x.

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

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