pylab in wx application - python

when I try make a picture with pylab
import pylab
pylab.plot([0,1,2,3],[10,50,30,40])
pylab.savefig('graph.png')
in a wx application, no returned the terminal control.

I imagine that you are calling the wx main-loop in your main (only?) thread. However can you clarify the context of your code snippet? How do you make it into a "wx application" and why do you want terminal control? For example, do you want to see your figure on screen while also entering stuff at the terminal. Or do you want to just save it, without it showing on screen?
Anyway, the code snippet you give runs just fine for me, but if I do
import pylab
pylab.plot([0,1,2,3],[10,50,30,40])
pylab.savefig('graph.png')
pylab.plot()
Then if I run your code ...
as "python snippet.py", then it just writes the file and exits, fine.
from "ipython -wthreads", it shows the plot, saves it and returns control to me.
from "ipython", then it does it's thing and never returns control.
This is because pylab.plot() calls the main loop of a GUI (gtk in my case, I expect wx will do the same).

Related

Tkinter library code not responding to Spyder breakpoints

I was trying to understand the Tkinter library code a little bit better, so I've been trying to place breakpoints in different places and understand the flow of code. To my surprise, the debugger does not stop at many points of the library code that I know are being executed.
I'm unclear on whether this is a spyder bug, or something funny in how Tkinter creates a loop for the GUI / interfaces with the OS.
This is the simple test-driving code that I am using:
from IPython import get_ipython
get_ipython().magic('reset -sf')
import tkinter as tk
x = tk.Pack()
I initially modified tkinter's init.py file at line 2144 to introduce a breakpoint here:
pack = configure = config = pack_configure
To my consternation, the debugger never stops here, which is very surprising to me given that commenting this line out causes an error in my test-drive code above.
I then added a simple print statement after line 2144 above,
sys.stdout.write('beep')
sys.stdout.flush()
Again, to my surprise, the 'beep' is only printed occasionally / seemingly stochastically. This is despite me clearing the workspace in the test driving script (the ipython %reset -sf command), as well as closing and re-opening anaconda/spyder.
Is there some kind of remedy to this, so that I can get more consistent behavior?
Thanks.

ipywidgets widgets values not changing

I am trying to get output from my ipywidgets widgets in Microsoft Azure Notebooks running Jupyter Notebooks in Python 3.6. However, it does not return new values when I get them. This also applies to the event handlers/interact never being called for other widgets.
I have tried putting in different initial values, using different types of widgets (Text, Textarea, Checkbox, Button, ToggleButton). I have tried getting the w.value, ipywidgets.interact, w.observe, and w.on_click on Buttons.
A test that I did:
import time
import ipywidgets as widgets
from IPython.display import display
w = widgets.Text(disabled=False)
display(w)
while True:
print(w.value)
time.sleep(1)
I expect that when I enter something into the Text field, that it will output that text, but instead it continues printing out what it started with. There are no errors. So, for the above example, regardless of what I input into the resultant Text field, all that is printed is empty lines.
The problem is that communication between widgets and the Python
kernel is asynchronous and confusing.
time.sleep(...) in the cell only blocks the Python interpreter and does
not allow the widget Javascript implementation to send the changed value to the Python
kernel (because the Python kernel is blocked and not doing anything).
If you create the widget and then modify the widget text entry and then evaluate
w.value in the next cell interactively you will see the changed value.
See further discussion here (look for "async"):
https://github.com/AaronWatters/jp_proxy_widget/blob/master/notebooks/Tutorial.ipynb
In general if you want to force the Python interpreter to see some value sent from the Javascript widget implementation the Javascript side must call back to the Python interpreter in some way and the Python interpreter cannot be blocked by sleep or any other such mechanism.
This code doesn't work as intended in a normal notebook server, so probably won't work in Azure either. I suspect you need a thread process to read from the updated widget. Try this and see if you get anything printing in Azure Notebooks as you change the text field.
import time
import ipywidgets as widgets
from IPython.display import display
w = widgets.Text(disabled=False)
display(w)
def print_text(widget):
print(widget['new'])
w.observe(print_text, names='value')

Launch Tkinter GUI before importing a module (delay import until certain class has instantiated)

DISCLAIMER *Hey there before anyone says this question already exists i have checked they either dont relate to what im trying to do or i dont understand them. for instance, i tried a splash screen Tkinter Show splash screen and hide main screen until __init__ has finished
but it still doesn't launch until the external script has finished importing.
ok so i have a tkinter application which uses a backend function from an external script. This script is working with large datasets and so it takes a good 15-20 seconds to compute although after the initial loading there is no delay.
The problem is that when i import this function to my tkinter GUI script it takes a while to launch as it is loading the module ofcourse.
I was wondering if there was either a way to launch my GUI first and then load the module while the application is running or lauch a loading screen while the module is importing.
any useful links will do, i have tried messing about with constructors in the external script but in that script i have a bunch of code outside any functions as these are required by all the functions in that script.
Thanks in advance for any advice.
Code:
from Content import print_similar_animes # functions from external script
from Content import get_id_from_partial_name
#These functions are within a class and are only
#called when a button is clicked.
def GetPartial(self):
partial=self.NameEntry.get()
get_id_from_partial_name(partial).
def Rec(self):
user_anime=self.NameEntry2.get()
print_similar_animes(user_anime)
It looks you coupled data loading with UI building. They don't have to be like that. Decouple it, make it load after the click of a button only, or use after() to delay or to load small chunks of data. Or use threads some will say. See here for after method.
Haha i solved it. To delay an import until the class is instantiated, the import must be inside a method.
LIKE SO:
def GetPartial(self):
from Content import get_id_from_partial_name #import here
partial=self.NameEntry.get()
get_id_from_partial_name(partial).
def Rec(self):
from Content import print_similar_animes # import here
user_anime=self.NameEntry2.get()
print_similar_animes(user_anime)
NOTE - Putting the import inside the class but outside of any method still causes the import to occur when the module is initialized.

PyDev Seaborn in Eclipse: "QPixmap: It is not safe to use pixmaps outside the GUI thread" on PyDev autocompletion popup

I'm getting the error
QPixmap: It is not safe to use pixmaps outside the GUI thread
when manually entering the following statements in Seaborn in the ipython-shell using PyDev in Eclipse:
import matplotlib.pyplot as mpl
import seaborn as sns
import pandas as pd
import numpy as np
# Turn interactive mode off:
mpl.ioff()
# Create some example Data:
df = pd.DataFrame({'A':np.random.rand(20),'B':np.random.rand(20)})
# Create seaborn PairGrid instance:
pg = sns.PairGrid(df)
At this point when I continue the last statement with a dot to e.g. chain a map()-method, like this:
pg = sns.PairGrid(df).
then Eclipse is trying to show a popup of all possible completions but that popup is immediatly getting closed and the console is getting filled with the aforementioned error, 42 lines of it to be precise.
I can continue and do this without problem:
gp = sns.PairGrid(df).map(mpl.scatter)
gp.fig.show()
And I get my plot just fine.
The same happens when doing sns.JointGrid(df.A,df.B). and sns.FacetGrid(df).
While playing around earlier I also got into situations where the console was actually killed by this error, I just can't replicate the steps that lead to this anymore.
Researching on this site it looked like it has to do with threading which I'm not using at all. Does Seaborn use it?
I want to create my plots by first creating a Grid/Figure and doing the plotting later, but this error suggests that this isn't a safe way to do things though the Seaborn doc says it's fine to do it like that:
https://seaborn.github.io/generated/seaborn.FacetGrid.html
EDIT:
When doing the same thing in Spyder I'm not getting the error but this warning when doing gp.fig.show():
C:\Anaconda2\lib\site-packages\matplotlib\figure.py:397: UserWarning:
matplotlib is currently using a non-GUI backend, so cannot show the figure
"matplotlib is currently using a non-GUI backend, "
When interactive mode is off I'm not seeing any graphic. With interactive mode on I'm still seeing the warning but get the graphic inline.
No popup in either case though. In Eclipse I'm getting both the error and the popup.
EDIT 2:
Running the whole thing as a script in Eclipse does not produce any error, only the manual entering like described above does.
I took a look at https://github.com/fabioz/Pydev/blob/master/plugins/org.python.pydev/pysrc/pydevconsole.py and the issue is that the code-completion on PyDev is being triggered in a secondary thread, not in the main (UI) thread.
I.e.: the code completion in the interactive console is not expecting that it'll touch code that'll actually interact with the gui.
For this to work, the completion command has to be queued for the main thread (as the regular commands are queued) and the thread has to wait for it to finish to then return its value.
Please report this as an issue in the PyDev tracker: https://www.brainwy.com/tracker/PyDev/ (i.e.: code-completion in the interactive console should happen in the UI thread).

Working with PyQt4

I''ve been experimenting with PyQt4 and I'm having a hard time with getting it to run the way I need it to. What I'm looking for is a way to have my own code run in a widget independent of gui events. Is there something like an 'onRender' command for your widget to run bckground code?

Categories