2

ipythonblocks に基づいていくつかの単純な非同期実行アニメーションを作成しようとしています. を使用してセル出力領域を更新しようとしてclear_output()grid.show()ます.

テキスト出力については、スレッド化された IPython ノートブックのセルごとの出力で手法の基礎が説明されているため、同じ方法を使用して HTML 出力を分離するという単純な仮定がありました。グリッドを更新された HTML バージョンに繰り返し置き換えたいので、clear_output()グリッドのコピーが 1 つだけ表示されるようにします。

この提案された手法が、次のセルを使用したテキスト出力で機能することを確認しました。まずコンテキストマネージャ。

import sys
from contextlib import contextmanager
import threading

stdout_lock = threading.Lock()
n = 0

@contextmanager
def set_stdout_parent(parent):
    """a context manager for setting a particular parent for sys.stdout
    (i.e. redirecting output to a specific cell). The parent determines
    the destination cell of output
    """
    global n
    save_parent = sys.stdout.parent_header
    # we need a lock, so that other threads don't snatch control
    # while we have set a temporary parent
    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
            n += 1; print("Flushing", n)
            sys.stdout.flush()
            sys.stdout.parent_header = save_parent

次にテストコード

import threading
import time
class timedThread(threading.Thread):
    def run(self):
        # record the parent (uncluding the stdout cell) when the thread starts
        thread_parent = sys.stdout.parent_header
        for i in range(3):
            time.sleep(2)
            # then ensure that the parent is the same as when the thread started
            # every time we print
            with set_stdout_parent(thread_parent):
                print(i)

timedThread().start()

これにより、出力が提供されました

0
Flushing 1
1
Flushing 2
2
Flushing 3

そこで、サイクル間でセルをクリアするようにコードを変更しました。

import IPython.core.display

class clearingTimedThread(threading.Thread):
    def run(self):
        # record the parent (uncluding the stdout cell) when the thread starts
        thread_parent = sys.stdout.parent_header
        for i in range(3):
            time.sleep(2)
            # then ensure that the parent is the same as when the thread started
            # every time we print
            with set_stdout_parent(thread_parent):
                IPython.core.display.clear_output()
                print(i)

clearingTimedThread().start()

予想どおり、セルの出力領域は繰り返しクリアされ、最終的には読み取られました

2
Flushing 6

したがって、ipythonblocks を使用するときに同じ手法を使用してセルの出力領域をクリアすることは安全だと思いました。悲しいかな。このコード

from ipythonblocks import BlockGrid

w = 10
h = 10

class clearingBlockThread(threading.Thread):
    def run(self):
        grid = BlockGrid(w, h)
        # record the parent (uncluding the stdout cell) when the thread starts
        thread_parent = sys.stdout.parent_header
        for i in range(10):
            # then ensure that the parent is the same as when the thread started
            # every time we print
            with set_stdout_parent(thread_parent):
                block = grid[i, i]
                block.green = 255
                IPython.core.display.clear_output(other=True)
                grid.show()
            time.sleep(0.2)

clearingBlockThread().start()

実際に目的の最終状態 (緑色の対角線を持つブラック マトリックス) を生成しますが、中間ステップはセルの出力領域に表示されません。少し複雑なことに (?)、この例は Python 3 で実行されています。ここに投稿する前に確認したところ、予想される動作 (単純なアニメーション) が実際に Python 2.7 で発生することがわかりました。したがって、これが私が報告する必要がある問題であるかどうかを尋ねる必要があります。

4

0 に答える 0