(python) matplotlib pyplot show() .. 是否阻塞?
我一次又一次地遇到 show()
的麻烦,我确信我做错了什么,但不确定“正确”的方法来做我想做的事。
[我认为]我想要的是某种方法来阻塞主线程,直到 GUI 线程中发生事件,这样的事情第一次起作用:
from matplotlib import pyplot as p
from scipy import rand
im = (255*rand(480,640)).astype('uint8')
fig = p.figure()
ax = fig.add_subplot(111)
ax.imshow(im)
# just any mutable container for storing a click
s = [-1, -1]
def onclick(event):
if event.xdata is not None and event.ydata is not None:
s[0] = event.xdata
s[1] = event.ydata
p.close()
cid = fig.canvas.mpl_connect('button_press_event', onclick)
p.show()
print s
p.show()
阻塞直到 < code>p.close() 在事件处理程序中调用。但是,当第二次运行相同的代码时,它会超越 p.show()
并打印原始的 s, [-1, -1]
。
我读过关于 p.show() 是否可以或应该从同一程序多次调用的相互冲突的信息。它似乎被设计为使用一次,并且仅在脚本末尾使用一次。其他用例似乎以某种方式破坏了 pyplot(状态机?)。
我尝试使用 p.draw()
和 p.ion()
和 p.ioff()
的组合,但不能得到我想要的行为(要么事情没有正确阻止,要么情节没有在正确的时间出现)。
我还对事件处理程序如何在这里看到 s
以及这是否是传入/传出信息的糟糕方式感到困惑。如果我不使用数组或列表等可变容器,那么我想要由事件处理程序设置的信息就会作为局部变量丢失。是否有其他一些我错过的方法,GUI 线程可以将信号传递回主线程?有没有办法在继续之前在 main 中阻止来自事件处理程序的信号,而无需定期轮询或忙等待?
所以我想最终我的主要问题是:
是否有 p.show() 的简洁替代品,它可以实现我想要的功能(与 p.show() 的行为相同)有第一次),或者这种代码是否需要完全重新思考/重写?
I have run into this trouble with show()
over and over again, and I'm sure I'm doing something wrong but not sure of the 'correct' way to do what I want.
And [I think] what I want is some way to block in the main thread until an event happens in the GUI thread, something like this works the first time:
from matplotlib import pyplot as p
from scipy import rand
im = (255*rand(480,640)).astype('uint8')
fig = p.figure()
ax = fig.add_subplot(111)
ax.imshow(im)
# just any mutable container for storing a click
s = [-1, -1]
def onclick(event):
if event.xdata is not None and event.ydata is not None:
s[0] = event.xdata
s[1] = event.ydata
p.close()
cid = fig.canvas.mpl_connect('button_press_event', onclick)
p.show()
print s
the p.show()
blocks until p.close()
is called in the event handler. But when run the same code the second time, it races past the p.show()
and prints that original s, [-1, -1]
.
I have read conflicting information on whether or not p.show()
can or should be called more than once from the same program. It seems it was designed to be used once, and only once at the end of a script. Other use cases seem to break pyplot
somehow (state machine?).
I've tried to use combinations of p.draw()
and p.ion()
and p.ioff()
, but could not get the behaviour I wanted (either things weren't blocking properly or the plots weren't appearing at the right times).
I'm also confused about how the event handler is able to see s
at all here, and whether this is a poor way of passing in/out information. If I don't use a mutable container like an array or list, the information I want set by the event handler just gets lost as a local variable. is there some other method I'm missing out on , where the GUI thread can pass signals back to the main thread? is there a way to block in main, without periodic polling or busy waiting , for a signal from the event handler before continuing?
So I guess ultimately my main question is:
Is there a neat replacement for p.show()
, that does what I want (the same behaviour as p.show()
has the first time), or does this kind of code require a complete rethink/rewrite ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
几个不同质量的想法:
如果您不喜欢 s 作为全局变量,您可以使 onclick() 成为一个可调用对象,并将其附加到该对象上。
您的回调可以获取/释放锁来控制程序流(有点脏)。
您可以主动 poll 来控制程序流程(非常脏)。
您可以通过Fig.canvas.draw()手动控制图形的绘制
Couple ideas of varying quality:
If you don't like s being a global variable, you could make onclick() a callable object attach it to that.
Your callback could acquire/release a lock to control program flow (little dirty).
You could actively poll s to control program flow (very dirty).
You can manually control the drawing of your figures via fig.canvas.draw()
我今天能够解决我的问题。如果其他人有兴趣更改
show()
的行为,请继续阅读以了解如何执行此操作:我注意到 多次调用以显示支持 上的这段文字matplotlib 网页的 href="http://matplotlib.sourceforge.net/users/whats_new.html" rel="nofollow">新增内容 部分:
这是
1.0.1
版本的“新增功能”,在撰写本文时,synaptic 中的版本仍然是0.99.3
。我能够从源代码v1.0.1
下载并构建。我还需要满足依赖关系的其他软件包有libfreetype6-dev tk-dev tk8.5-dev tcl8.5-dev python-gtk2-dev
。现在有了
matplotlib.__version__ == 1.0.1
,以下代码阻止了我的预期:I was able to resolve my issue today. if anyone else is interested in changing the behaviour of
show()
, read on for how you can do it:I noticed this paragraph titled multiple calls to show supported on the what's new part of the matplotlib webpage:
This was in 'what's new' for version
1.0.1
, at time of writing the version in synaptic is still back on0.99.3
. I was able to download and build from sourcev1.0.1
. Additional packages I also required to satisfy dependencies werelibfreetype6-dev tk-dev tk8.5-dev tcl8.5-dev python-gtk2-dev
.Now with
matplotlib.__version__ == 1.0.1
, the following code blocks how I would expect:运行代码
直接在Python解释器(命令行)内
将其放入Python脚本并从命令行运行( "python script.py")
两者都会产生阻塞行为,这是可以的。
从解释器中显示两个图像,从命令行中仅显示第一个图像。
I noticed a difference between running the code
Directly within the Python interpretor (command line)
Putting it in a Python script and running it from the command line ("python script.py")
Both give a blocking behavior, which is ok.
From the interpretor both images appear, from the command line only the first appears.