In my Jupyter notebook, I want to execute some long running background jobs and display their status in a cell. I thought, before doing something difficult, I could start with a clock.
I have the following code in one cell
import ipywidgets as widgets
import time
from datetime import datetime as dt
from IPython.display import HTML
from IPython.display import display
import threading
out = widgets.Output()
#out.capture(clear_output=True, wait=True)
def display_time():
now = dt.now().strftime("%H:%M:%S")
display(HTML(f"""<h1><center>{now}</center></h1>"""))
def run_time():
while True:
time.sleep(1)
display_time()
out
When I call run_time() I get the time nicely updated every second, but my notebook is blocking on this cell. So I tried threading.Thread(target=run_time).start() but this somehow only updates the time whenever I do interactions with the notebook. How can I update the notebook even if I do not do any cell interactions?
You want to have a look at ipyrallel to run multi kernels in you notebook.
Here is a solved issue
Here is the documentation
Related
I'm trying to manufacture a button that, when clicked, will begin a loop that triggers some data collection and several live, updating plots.
I thought I had the plots and the loops sorted out well, but as soon as I try to incorporate the button things go south. My plots are now in my JupyterLab log, not in the command line where they had been appearing (and updating) before. Has anyone encountered this issue before? Or have a potential workaround?
Here is how my code is structured:
import csv
from datetime import datetime
import pyvisa as visa
import serial
import time
from time import sleep
import numpy as np
from IPython import display
from IPython.display import clear_output
import matplotlib.pyplot as plt
import sys
import ipywidgets as widgets
import voila
from ipywidgets import ToggleButtons
from ipywidgets import Button
import asyncio
import nest_asyncio
from asyncio import coroutine
nest_asyncio.apply()
%matplotlib widget #only widget, not notebook or inline, will keep my plots interactive
async def mainexp(n, s): #these all lead to different loops that collect + plot data smoothly
plt.clf()
data = asyncio.create_task(datacollect(n, s))
graphr = asyncio.create_task(graphloopr(n, s))
graphv = asyncio.create_task(graphloopv(n, s))
await asyncio.sleep(s)
## button to start data collection + plotting
startbutton = widgets.Button(description="Start")
out = widgets.Output()
def on_button_clicked(b):
with out:
clear_output(True)
print("Hello")
asyncio.run(datarun(10, 1))
#show()
startbutton.on_click(on_button_clicked)
display(startbutton, out)
At this point my machine tells me it is collecting data, "Hello" prints...the only issue is when it comes to graphing--and it's stored as a blank axis in my list of log entries...?
import camelot
import pandas as pd
import matplotlib
file = 'foo.pdf'
tables = camelot.read_pdf(file, pages='all', flavor='stream')
camelot.plot(tables[0], kind='text').show()
The matplot window opens and suddenly closes in a flash without any user input whatsoever.
I want the window to remain open to examine the contents.
Edit: I am using Windows 11 and Python 3.9, running the code on Pycharm and it's the system interpreter rather than a virtual environment.
Not sure if you ever found your answer, but I will attach what I have found from the following answer by swenzel: https://stackoverflow.com/a/33062819
The plot is opening in a non-blocking window which disappears as soon as the script finishes. You can override this by importing matplotlib and using plot.show(block=True) at the end to show the window as a blocking window, which will keep the script from continuing until closed. See his code snippet below.
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("table.csv")
values = df["blah"]
values.plot()
print 1
df['blahblah'].plot()
print 2
plt.show(block=True)
Your code rewritten would look like the following:
import camelot
import pandas as pd
import matplotlib.pyplot as plt
file = 'foo.pdf'
tables = camelot.read_pdf(file, pages='all', flavor='stream')
camelot.plot(tables[0], kind='text')
plt.show(block=True)
In a published Jupyter notebook is there a way to insert a widget that says "running" or something similar when I am running a function.
I am aware of the tqdm function but to the best of my knowledge this is only when the function / process contains a for-loop.
I currently have a series of dropdown widgets with a submit button but some of the functions take a while for the calcs to run so i have no way of telling if the're running or not
Cheers
The way I have done this in the past is to have a function as a context manager, that displays some value to a Text widget to indicate that the function is running. You could also use an Output widget to display a indeterminate 'progress' bar like the one below:
https://www.iselect.com.au/content/themes/iselect/images/post/loader.gif
import ipywidgets as ipyw
import time
from contextlib import contextmanager
label = ipyw.Text('Ready')
button = ipyw.Button(description='Click me')
#contextmanager
def show_loading():
label.value = 'Running...'
yield
label.value = 'Ready'
def long_running_function(self):
with show_loading():
time.sleep(2)
button.on_click(long_running_function)
display(button)
display(label)
I am writting a jupyter notebook in which at the begining I am creating a complex tab ipywidget for the user to select some inptus (see picture). I am wondering if there is any way to hide to the user the code cell that contains the code to create that widget.
I saw on this forum some questiosn about hiding code when exporting the notebook but in my case the user will access the j_notebook online. Just would like to avoid complexity by hiding some code cells
in module.py
import ipywidgets as ipyw
from IPython.display import display
button = ipyw.Button('Try this:')
out = ipyw.Output()
def print_it(button):
with out:
print('You clicked it')
button.on_click(print_it)
display(ipyw.VBox(children=[button, out]))
In your notebook:
import module
This page talks about the usage of ipython for interactive plotting: http://matplotlib.org/users/shell.html
According to that page, by default the %run command that is used to run scripts in ipython shuts down interactive mode. Is there an option to run the script in interactive mode as well?
I want the plotting commands in a script to take effect in the plotting figure as soon as they are run as if they are entered from the console interactively.
For example, consider the very simple script below:
# try.py:
# run in ipython that is started with
# ipython --pylab
# using
# %run -i try.py
from numpy import *
from time import sleep
ion()
x = randn(10000)
hist(x,100)
show()
sleep(5)
xlabel('labalu')
When run from ipython as indicated in the comment, this script waits 5 seconds, than shows everything. What I want is this: When run from ipython as indicated in the comment, the script should show the histogram immediately, wait 5 seconds, than update the figure to show the x label.
Moving ion() so it is after show() does what I think you want. Why it doesn't in the higher position, I do not know offhand.
If wx is used as the backend, following works:
#run in ipython that is started with ipython --pylab=wx
from numpy import *
import matplotlib
matplotlib.use('WX')
import wx
from time import sleep
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
x = np.random.uniform(0,1,100)
plt.plot(x)
plt.show()
wx.Yield()
for i in reversed(range(5)):
print(i)
sleep(1)
plt.xlabel('labl')
wx.Yield()
So, wx.Yield() lets interaction with the figure window. This also works when the script is run with normal python, but the figure is closed at the end of the script automatically.
Any cross-backends solutions (or solutions for qt/tk ) are still well come.
And below is a solution that works with both the wx and qt backends. gcf().canvas.flush_events() does the trick.
# try.py:
# run in ipython that is started with
# ipython --pylab
# using
# %run -i try.py
from numpy import *
import matplotlib
from time import sleep
x = randn(10000)
hist(x,100)
show()
ion()
gcf().canvas.flush_events()
sleep(5)
xlabel('labalu')
show()