python - How to save ipywidget output and link it to a button to run another function with saved inputs
问题描述
This is going to be a kind of long question so I'll try to break it down as much as I can so please bear with me. My idea is to create an jupyter notebook app using jupyter widgets. My app will get some information using an API but it needs some inputs first which are time and entity name that also have some metadata. Because I have different ipywidgets incorporated here (SelectMultiple,2 Date pickers widgets (start, end) and button that would finally will load the function to get the data from the database.)
Currently my widgets look like this:
I'm able to obtain multiple entities ('Wells') (with its own metadata and assign an start and end date and save it in a dictionary). I have created a button but I'm having a hard time to be able to link the button to the already saved data to run my function everytime I run click in 'run'. Here's my code:
#I created a class to add multiple widgets
class SelectMutipleInteract(widgets.HBox):
def __init__(self,api_obj):
#In my init function I'm obtaining all the entities to be stored in the Selectmultiple widget
env='prod'
pre_df = api_obj.search_sites_by_name('',env).set_index('site_id').sort_index(ascending=True)
pre_df = pre_df[pre_df['db'].str.contains('jon')]
self.pre_df = pre_df
self.w = widgets.SelectMultiple(
options = pre_df.name.values,
rows = len(pre_df),
description = 'Wells',
disabled = False)
#From that same data I get initial start and end dates (which I'll be able to change based on the time I want)
try:
self.start_date = datetime.strptime(self.pre_df.sort_values(by='date_created')['date_created'].values[0],'%Y-%m-%dT%H:%M:%SZ')
self.start_date = pd.Series(self.start_date).dt.round('H')[0]
except:
'TypeError'
try:
self.start_date = datetime.strptime(self.pre_df.sort_values(by='date_created')['date_created'].values[0],'%Y-%m-%dT%H:%M:%S.%fZ')
self.start_date = pd.Series(self.start_date).dt.round('H')[0]
except:
'TypeError'
try:
self.end_date = datetime.strptime(self.pre_df.sort_values(by='last_transmission',ascending=False)['last_transmission'].values[0],'%Y-%m-%dT%H:%M:%SZ')
self.end_date = pd.Series(self.end_date).dt.round('H')[0]
except:
'TypeError'
try:
self.end_date = datetime.strptime(self.pre_df.sort_values(by='last_transmission',ascending=False)['last_transmission'].values[0],'%Y-%m-%dT%H:%M:%S.%fZ')
self.end_date = pd.Series(self.end_date).dt.round('H')[0]
except:
'TypeError'
# I created the rest of the widgets
self.w1 = widgets.DatePicker(
description='Pick Start Date',
value = self.start_date)
self.w2 = widgets.DatePicker(
description='Pick End Date',
value=self.end_date)
self.w3 = widgets.Button(
description='Run',
button_style='info')
self.selectors = [self.w,self.w1,self.w2,self.w3]
#I think this as a super class and then each object to be assigned together
super().__init__(children=self.selectors)
self._set_observes()
def _set_observes(self):
self.selectors1 = self.selectors[:3]
for widg in self.selectors1:
widg.observe(self._observed_function_widgets1, names='value')
#Observed function will work as the place to store the metadata
def _observed_function_widgets1(self,widg):
self.dict = {}
self.list_a = []
for widg in self.selectors1:
if type(widg.get_interact_value())==tuple:
self.list_a.append(widg.get_interact_value())
else:
self.list_a.append(datetime.strftime(widg.get_interact_value(), '%Y-%m-%d %H:%M:%S'))
for well in self.list_a[0]:
a = self.pre_df.loc[self.pre_df['name']==well,:]
self.dict[well]= {'domain':a['db'],'site_slug':a['slug'],'start_date':self.list_a[1],
'end_date':self.list_a[2]}
print(self.dict)
#This is where I put the connection of the button but I'm getting an error
self.w3.on_click(self._on_button_clicked(self.dict))
def _on_button_clicked(self,dict1):
#Here I should run the final function
print(1)
print(dict1)
SelectMutipleInteract(api_obj)
The error that I get when I press the button (after I already selected entities and times) is
{'SHB 67-34': {'domain': site_id
183 jonah-energy
Name: db, dtype: object, 'site_slug': site_id
183 10004-24
Name: slug, dtype: object, 'start_date': '2019-09-26 15:00:00', 'end_date': '2020-12-17 21:00:00'}, 'SHB 75-34': {'domain': site_id
184 jonah-energy
Name: db, dtype: object, 'site_slug': site_id
184 10005-40
Name: slug, dtype: object, 'start_date': '2019-09-26 15:00:00', 'end_date': '2020-12-17 21:00:00'}, 'SHB 77-34': {'domain': site_id
185 jonah-energy
Name: db, dtype: object, 'site_slug': site_id
185 10006-46
Name: slug, dtype: object, 'start_date': '2019-09-26 15:00:00', 'end_date': '2020-12-17 21:00:00'}}
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
TypeError: 'NoneType' object is not callable
The whole idea is to (once the data has been selected and stored) then run the final function but I'm having a hard time conceptualize the creation on the button give that you need to run the several widgets first to get the data and store it and then click the button to run the function with that data they way I'm creating the widgets layout together.
Any help would really appreciate it.
解决方案
这里的问题真的很微妙。
您需要将可调用对象 self._on_button_clicked
传递给self.w3.on_click
. 您当前的代码调用该self._on_button_clicked
函数,并传递该函数的返回值,该值确实为 None。然后,当您单击按钮时,on_click
尝试调用 None,因此您的错误。
试着想想这段代码:
value = self._on_button_clicked(self.dict)
self.w3.on_click(value)
这与当前代码的实现完全相同,但希望它能说明为什么您所拥有的代码不起作用。value
是无,然后您告诉按钮在单击它时调用无。
为避免这种情况,请进行以下更改:
self.w3.on_click(self._on_button_clicked)
# 传递函数本身,而不是调用该函数的结果。更改观察到的函数代码以获取正文中所需的变量。
def _on_button_clicked(self, button): # the button arg gets passed, but you don't need it.
#Here I should run the final function
print(1)
print(self.dict) # grab the instance variables you want
在大多数情况下,最好在观察到的函数中获取所需的变量,而不是在进行赋值时尝试传递它们on_click
。如果您真的无法在函数中获取所需的变量(例如,变量超出范围),那么您可以使用 functools.partial。
推荐阅读
- python - 如何连接字符串数组中的元素?
- python - 如果在本地和云上运行,`requests` 会为同一脚本返回不同的结果
- azure - Azure WebApps 泄露句柄“无中生有”
- python - 从具有特定列的最接近值的数据框中选择/分组行
- python - 为分组的 pandas 数据框创建散点图
- handlebars.js - Handlebars 模板中的切换功能
- python - subprocess.Popen() 不会运行 python 脚本,找不到 python 命令
- java - 如何将csv字符串转换为字节流
- jenkins - Jenkins 节点/代理无法连接到主 jenkins 服务器 - 无效的 X-Instance-Identity
- git - Gitk 由于奇怪的错误而无法工作 macOS 11 或更高版本需要