如何在所有线程完成后强制IPython只给我一个新提示

时间:2011-10-20 12:48:51

标签: python multithreading ipython

我正在使用IPython开发基于多线程套接字的客户端 - 服务器类型的东西。问题是IPython试图在我的一些线程完成运行之前给它命令提示符提示。然后丢失线程的调试文本输出。

当所有线程都运行完毕后,有没有办法让IPython只给我一个新提示?

由于

2 个答案:

答案 0 :(得分:2)

尝试

threads = [threading.Thread(target=myFunc) for i in range(n)]
for t in threads:
    t.start()
...
for t in threads:
    t.join()

其中threads是您的threading.Thread个实例的列表。这将导致主线程等待所有工作线程完成。

答案 1 :(得分:0)

您可以将调试输出发送到某种缓冲区,然后安排IPython在每次打印提示时打印此缓冲区的内容,而不是等待线程完成。要查看更多调试输出,请输入一个空行以使IPython将缓冲区刷新到控制台:

def ipython_logging():
    import logging.handlers
    # setup a logging handler to actually print output to the console
    console = logging.StreamHandler()
    console.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
    console.setLevel(logging.DEBUG)
    # then setup a handler that buffers the output.  the float('inf')'s suppress automatic flushing.
    memory = logging.handlers.MemoryHandler(capacity=float('inf'),
                                            flushLevel=float('inf'),
                                            target=console)
    memory.setLevel(logging.DEBUG)
    logging.root.addHandler(memory)
    logging.root.setLevel(logging.DEBUG)
    # tell IPython to flush the buffer every time it prints a prompt.
    import IPython
    def flush_log(self, *args, **kwargs):
        memory.flush()
        raise IPython.ipapi.TryNext
    ip = IPython.ipapi.get()
    ip.set_hook("generate_prompt", flush_log)

然后,您可以从您的主题进行记录:

import logging
import threading
import time
import random

LOGGER = logging.getLogger(__name__)

class MyThread(threading.Thread):
    def __init__(self, threadnum):
        super(MyThread, self).__init__()
        self.__threadnum = threadnum
    def run(self):
        freq = random.randrange(1,10)
        count = random.randrange(20)
        for i in range(count):
            time.sleep(freq)
            LOGGER.debug("output from #%d, i=%d, freq=%d", self.__threadnum, i, freq)

,使用时可能看起来像这样:

$ ipython 
Python 2.7.1 (r271:86832, Apr 12 2011, 16:15:16) 
Type "copyright", "credits" or "license" for more information.

IPython 0.10.2 -- An enhanced Interactive Python.

In [1]: import soithreads

In [2]: soithreads.ipython_logging()

In [3]: [soithreads.MyThread(n).start() for n in range(3)]
Out[3]: [None, None, None]

In [4]: 

In [5]: 

In [6]: 

In [7]: 
DEBUG:soithreads:output from #1, i=0, freq=3

In [8]: 

In [9]: 
DEBUG:soithreads:output from #1, i=1, freq=3

In [10]: 

In [11]: 

In [12]: 

In [13]: 
DEBUG:soithreads:output from #2, i=0, freq=8

In [14]: 

In [15]: 
DEBUG:soithreads:output from #1, i=2, freq=3
DEBUG:soithreads:output from #0, i=0, freq=9

In [16]: 

In [17]: 
DEBUG:soithreads:output from #1, i=3, freq=3

In [18]: 

In [19]: 

In [20]: 

In [21]: 

In [22]: 

In [23]: 
DEBUG:soithreads:output from #1, i=4, freq=3

In [24]: 

In [25]: 
DEBUG:soithreads:output from #2, i=1, freq=8

In [26]: 

In [27]: 

In [28]: 

In [29]: 
DEBUG:soithreads:output from #1, i=5, freq=3
DEBUG:soithreads:output from #0, i=1, freq=9

In [30]: 

In [31]: 

In [32]: 

In [33]: 

In [34]: 

In [35]: 
DEBUG:soithreads:output from #2, i=2, freq=8
DEBUG:soithreads:output from #0, i=2, freq=9
DEBUG:soithreads:output from #2, i=3, freq=8
DEBUG:soithreads:output from #0, i=3, freq=9
DEBUG:soithreads:output from #2, i=4, freq=8
DEBUG:soithreads:output from #0, i=4, freq=9
DEBUG:soithreads:output from #0, i=5, freq=9
DEBUG:soithreads:output from #0, i=6, freq=9

In [36]: