Jupyter == 4.1.0,Python == 2.7.10,IPython == 4.2.0
我正在为我的Jupyter笔记本编写一个SQL UI,并希望合并多线程,以便我可以在一个单元格中运行查询,并在查询运行时继续在其他单元格中工作。
我遇到的问题是,如果我在一个单元格中执行查询,输出将显示在最后执行的单元格的输出提示中,而不是在执行的单元格的输出提示中查询。
我搜索了内部网并发现this clever trick,但我认为它已经过时和/或不再适用于我的Jupyter版本。当我运行它时,我只获得上次执行的任何单元格的输出。因此,如果我同时运行两者,我只获得最后执行的输出,而不是输出打印以同时分离单元格。
所以我有我的上下文管理器设置parent_header
:
import sys
import threading
from contextlib import contextmanager
# we need a lock, so that other threads don't snatch control
# while we have set a temporary parent
stdout_lock = threading.Lock()
@contextmanager
def set_stdout_parent(parent):
"""a context manager for setting a particular parent for sys.stdout
the parent determines the destination cell of output
"""
save_parent = sys.stdout.parent_header
with stdout_lock:
sys.stdout.parent_header = parent
try:
yield
finally:
# the flush is important, because that's when the parent_header actually has its effect
sys.stdout.flush()
sys.stdout.parent_header = save_parent
我基本上希望能够获得单元格[1]中的parent_header
并将单元格[2]的输出重定向到输入[1]。
示例:
获取[1]中的parent_header
:
In[1]: t = sys.stdout.parent_header
然后将运行以下代码,但输出应打印到Out [1](当前,我运行此代码时没有输出):
In [2]: with set_stdout_parent(t):
print 'FOO'
哪个应该产生:
In[1]: t = sys.stdout.parent_header
Out[1]:'FOO'
答案 0 :(得分:0)
您可以结合使用 ipywidgets.Output
(docs) 和锁定:
jupyter 单元格中的代码:
# In[1]:
from threading import Thread, Lock
import time
from ipywidgets import Output
# In[2]:
output1 = Output()
output1
# In[3]:
output2 = Output()
output2
# In[4]:
print_lock = Lock()
def t1_main():
for i in range(10):
with print_lock, output1:
print('thread1', i)
time.sleep(0.5)
def t2_main():
for i in range(10):
with print_lock, output2:
print('thread2', i)
time.sleep(0.5)
output1.clear_output()
output2.clear_output()
t1 = Thread(target=t1_main)
t2 = Thread(target=t2_main)
t1.start()
t2.start()
t1.join()
t2.join()
答案 1 :(得分:0)
ipywidgets.Output
的文档中有一节是关于 interacting with output widgets from background threads。使用 Output.append_stdout
方法不需要锁定。 this answer 中的最后一个单元格可以替换为:
def t1_main():
for i in range(10):
output1.append_stdout(f'thread1 {i}\n')
time.sleep(0.5)
def t2_main():
for i in range(10):
output2.append_stdout(f'thread2 {i}\n')
time.sleep(0.5)
output1.clear_output()
output2.clear_output()
t1 = Thread(target=t1_main)
t2 = Thread(target=t2_main)
t1.start()
t2.start()
t1.join()
t2.join()