(python) matplotlib pyplot show() .. 是否阻塞?

发布于 2024-11-10 15:42:39 字数 1258 浏览 4 评论 0原文

我一次又一次地遇到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

等往事风中吹 2024-11-17 15:42:39

几个不同质量的想法:

如果您不喜欢 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()

暮年慕年 2024-11-17 15:42:39

我今天能够解决我的问题。如果其他人有兴趣更改 show() 的行为,请继续阅读以了解如何执行此操作:

我注意到 多次调用以显示支持 上的这段文字matplotlib 网页的 href="http://matplotlib.sourceforge.net/users/whats_new.html" rel="nofollow">新增内容 部分:

一个长期存在的请求是支持对 show() 的多次调用。这很困难,因为很难在操作系统、用户界面工具包和版本之间获得一致的行为。 Eric Firing 在跨后端合理化显示方面做了很多工作,其期望的行为是使显示提升所有新创建的数字并阻止执行直到它们关闭。重复调用 show 应该会产生自上次调用以来新创建的数字。 Eric 对他有权访问的用户界面工具包以及版本和平台进行了大量测试,但不可能对所有这些进行测试,因此请向邮件列表和错误跟踪器报告问题。

这是 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 ,以下代码阻止了我的预期:

import matplotlib.pyplot as p
from scipy import eye
p.imshow(eye(3))
p.show()
print 'a' 
p.imshow(eye(6))
p.show()
print 'b' 
p.imshow(eye(9))
p.show()
print 'c' 

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:

A long standing request is to support multiple calls to show(). This has been difficult because it is hard to get consistent behavior across operating systems, user interface toolkits and versions. Eric Firing has done a lot of work on rationalizing show across backends, with the desired behavior to make show raise all newly created figures and block execution until they are closed. Repeated calls to show should raise newly created figures since the last call. Eric has done a lot of testing on the user interface toolkits and versions and platforms he has access to, but it is not possible to test them all, so please report problems to the mailing list and bug tracker.

This was in 'what's new' for version 1.0.1, at time of writing the version in synaptic is still back on 0.99.3. I was able to download and build from source v1.0.1. Additional packages I also required to satisfy dependencies were libfreetype6-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:

import matplotlib.pyplot as p
from scipy import eye
p.imshow(eye(3))
p.show()
print 'a' 
p.imshow(eye(6))
p.show()
print 'b' 
p.imshow(eye(9))
p.show()
print 'c' 
咿呀咿呀哟 2024-11-17 15:42:39

运行代码

  1. 我注意到

    直接在Python解释器(命令行)内

  2. 将其放入Python脚本并从命令行运行( "python script.py")

两者都会产生阻塞行为,这是可以的。

从解释器中显示两个图像,从命令行中仅显示第一个图像。

I noticed a difference between running the code

  1. Directly within the Python interpretor (command line)

  2. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文