4

我有一个记录数据并需要一段时间才能完成的功能。在记录数据时,我想要一个按钮,按下该按钮后,会显示自数据采集开始以来已经过去了多少时间。

这可以在 Jupyter 中完成吗?

我遇到了问题,因为数据采集阻止了小部件激活,如果我尝试在后台运行小部件,它on_click在数据采集完成之前不会收到事件。另一方面,如果我将数据采集发送到后台,那么一旦后台作业完成,数据就会丢失。

后台作业

from IPython.lib.backgroundjobs import BackgroundJobManager
from IPython.core.magic import register_line_magic
from IPython import get_ipython

jobs = BackgroundJobManager()

@register_line_magic
def background_job(line):
    ip = get_ipython()
    jobs.new(line, ip.user_global_ns)

定时器按钮

import ipywidgets as widgets
import time

def button_timer():
    t0 = 0
    button = widgets.Button(description="Measure time")
    def action(b):
        time_elapsed = time.perf_counter() - t0
        display("Time elapsed: {}".format(time_elapsed))
    button.on_click(action)

    display(button)
    t0 = time.perf_counter()

数据采集

import numpy as np
import pandas as pd
import time

def acquire(a=None):
    time.sleep(10)
    print("Done")
    if a is None:
        return np.linspace(0, 10, 10)
    else:
        a = np.linspace(0, 10, 10)

## Implementation 1
# This fails because the `on_click` event for the button only runs after the data has been acquired.
button_timer()
data = pd.DataFrame()
data['x'] = np.linspace(0, 10, 10)
data['y'] = acquire()

## Implementation 2
# As before, the `on_click` event isn't activated until after the data has been acquired.
%background_job button_timer()
data = pd.DataFrame()
data['x'] = np.linspace(0, 10, 10)
data['y'] = acquire()

## Implementation 3
# This one fails as the data isn't actually updated
button_timer()
data = pd.DataFrame()
data['x'] = np.linspace(0, 10, 10)
# I can't use the equal sign as that isn't supported by the background job.
# %background_job data['y'] = acquire()
# If I pass in the data I want, the DataFrame isn't updated (even after I wait for the background job to finish)
%background_job acquire(data['y'])
display(data)

如果一切都失败了,我想一个选择是有一个完全在浏览器中运行的纯 JavaScript 计时器。

不过,我想知道是否有办法在 Python 中执行此操作(如果可能的话,让(最后)测量的时间可以在笔记本的其余部分中以编程方式访问)。

4

0 回答 0