Как я могу заставить IPython выдавать мне новое приглашение только после завершения всех потоков - PullRequest
2 голосов
/ 20 октября 2011

Я использую IPython для разработки многопоточной сокет-системы типа клиент-сервер. Проблема в том, что IPython пытается выдать командную строку до завершения работы некоторых из моих потоков. Отладочный текстовый вывод потока затем теряется.

Есть ли способ заставить IPython выдавать мне новое приглашение только после завершения всех потоков?

Спасибо

Ответы [ 2 ]

2 голосов
/ 20 октября 2011

Попробуйте

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 экземпляров. Это заставит основной поток ждать, пока все рабочие потоки не будут завершены.

0 голосов
/ 20 октября 2011

Вместо того, чтобы ждать завершения потока, вы можете вместо этого отправить отладочный вывод в какой-то буфер, а затем организовать 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]: 
...