(python) matplotlib pyplot show () .. блокировать или нет? - PullRequest
6 голосов
/ 31 мая 2011

Я снова и снова сталкиваюсь с этой проблемой с 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() до вызова p.close() в обработчике событий. Но когда тот же код запускается во второй раз, он пробегает мимо p.show() и печатает этот оригинальный s, [-1, -1].

Я прочитал противоречивую информацию о том, может ли p.show() вызываться или не вызываться более одного раза из одной и той же программы. Кажется, он был разработан для использования один раз и только один раз в конце сценария. Другие варианты использования, кажется, как-то ломают pyplot (конечный автомат?).

Я пытался использовать комбинации p.draw() и p.ion() и p.ioff(), но не смог получить желаемое поведение (либо вещи не блокировались должным образом, либо сюжеты не появлялись в нужное время ).

Меня также смущает, как обработчик событий вообще может видеть s здесь, и является ли это плохим способом передачи информации о входе / выходе. Если я не использую изменяемый контейнер, такой как массив или список, информация, которую я хочу установить в обработчике событий, просто теряется как локальная переменная. Есть ли какой-то другой метод, который я пропускаю, где поток GUI может передавать сигналы обратно в основной поток? Есть ли способ заблокировать в основном, без периодического опроса или ожидания занятого, сигнал от обработчика событий перед продолжением?

Итак, я думаю, что в конечном итоге мой главный вопрос:

Есть ли аккуратная замена для p.show(), которая делает то, что я хочу (такое же поведение, как у p.show() в первый раз), или этот тип кода требует полного переосмысления / переписывания?

Ответы [ 3 ]

2 голосов
/ 31 мая 2011

Пара идей разного качества:

Если вам не нравится, когда s является глобальной переменной, вы можете сделать onclick () вызываемым объектом, прикрепив его к этому.

Ваш обратный вызов можетполучить / снять блокировку для контроля выполнения программы (немного грязно).

Вы можете активно опрашивать управление потоком программы (очень грязно).

Вы можете вручную управлять рисованием ваших фигур с помощьюfig.canvas.draw ()

1 голос
/ 01 июня 2011

Мне удалось решить мою проблему сегодня.если кто-то еще заинтересован в изменении поведения show(), читайте дальше, чтобы узнать, как это можно сделать:

Я заметил этот абзац под названием несколько вызовов, чтобы показать поддерживаемые на Что нового часть веб-страницы matplotlib:

Давний запрос заключается в поддержке нескольких вызовов show ().Это было трудно, потому что трудно получить согласованное поведение в операционных системах, наборах инструментов и версиях интерфейса пользователя.Эрик Фиринг проделал большую работу по рационализации шоу во всех бэкэндах, с желаемым поведением, чтобы шоу поднимало все вновь созданные фигуры и блокировало исполнение до их закрытия.Повторные вызовы для показа должны поднять вновь созданные цифры с момента последнего вызова.Эрик много тестировал наборы пользовательских интерфейсов, версии и платформы, к которым у него есть доступ, но проверить их все невозможно, поэтому, пожалуйста, сообщите о проблемах в список рассылки и систему отслеживания ошибок.

Это было в «Что нового» для версии 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' 
0 голосов
/ 26 августа 2011

Я заметил разницу между выполнением кода

  1. Непосредственно в интерпретаторе Python (командная строка)

  2. Помещение в скрипт Pythonи запустив его из командной строки ("python script.py")

Оба дают блокирующее поведение, что нормально.

Из интерпретатора появляются оба изображения,из командной строки появляется только первое.

...