Подтвердить что ты не робот

Matplotlib - отобразить график движения, а затем вернуться к основному коду

Это MWE того, что мне нужно, адаптировано из этого вопроса:

from matplotlib.pyplot import plot, draw, show

def make_plot():
    plot([1,2,3])
    draw()
    print 'continue computation'

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = raw_input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

show()

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

Вместо этого я получаю сообщение о том, что окно с графиком появляется после, код не работает.


Добавить 1

Я пробовал следующее с теми же результатами, окно графика появляется в конце кода, а не раньше:

from matplotlib.pyplot import plot, ion, draw

ion() # enables interactive mode
plot([1,2,3]) # result shows immediately (implicit draw())
# at the end call show to ensure window won't close.
draw()

answer = raw_input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

То же самое происходит, если я изменяю draw() для show().


Добавить 2

Я пробовал следующий подход:

from multiprocessing import Process
from matplotlib.pyplot import plot, show

def plot_graph(*args):
    for data in args:
        plot(data)
    show()

p = Process(target=plot_graph, args=([1, 2, 3],))
p.start()

print 'computation continues...'

print 'Now lets wait for the graph be closed to continue...:'
p.join()

что приводит к ошибке Python kernel has crashed в Canopy с сообщением:

The kernel (user Python environment) has terminated with error code -6. This may be due to a bug in your code or in the kernel itself.

Output captured from the kernel process is shown below.

[IPKernelApp] To connect another client to this kernel, use:
[IPKernelApp] --existing /tmp/tmp9cshhw.json
QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries.
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: ../../src/xcb_io.c:274: poll_for_event: La declaración `!xcb_xlib_threads_sequence_lost' no se cumple.

Я должен упомянуть, что я запускаю Canopy в elementary OS, который основан на Ubuntu 12.04.


Добавить 3

Также попытался решение опубликовано в этом вопросе:

import numpy
from matplotlib import pyplot as plt

if __name__ == '__main__':
    x = [1, 2, 3]
    plt.ion() # turn on interactive mode
    for loop in range(0,3):
        y = numpy.dot(x, loop)
        plt.figure()
        plt.plot(x,y)
        plt.show()
        _ = raw_input("Press [enter] to continue.")

Это отображает окна с пустыми окнами по мере продвижения кода (то есть: пользователь нажимает [enter]) и отображает только изображения после завершения кода.

Это решение (также в том же вопросе) даже не отображает окна графика:

import numpy
from matplotlib import pyplot as plt
if __name__ == '__main__':
    x = [1, 2, 3]
    plt.ion() # turn on interactive mode, non-blocking `show`
    for loop in range(0,3):
        y = numpy.dot(x, loop)
        plt.figure()   # create a new figure
        plt.plot(x,y)  # plot the figure
        plt.show()     # show the figure, non-blocking
        _ = raw_input("Press [enter] to continue.") # wait for input from the user
        plt.close()    # close the figure to show the next one.
4b9b3361

Ответ 1

Вы можете использовать plt.show(block=False), который напрямую избавляется от блокировки.

В вашем примере это может читать

from matplotlib.pyplot import plot, show

def make_plot():
    plot([1,2,3])
    show(block=False)
    print('continue computation')

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

Ответ 2

Ни одно из представленных решений не работает для меня. Я тестировал их с тремя разными IDE PyCharm, Spyder и Pyzo, используя (в настоящее время) последний Matplotlib 2.1 под Python 3.6.

Что для меня работает, хотя и не оптимально, заключается в использовании команды plt.pause:

import matplotlib.pyplot as plt

def make_plot():
    plt.plot([1, 2, 3])
#    plt.show(block=False)  # The plot does not appear.
#    plt.draw()             # The plot does not appear.
    plt.pause(0.1)          # The plot properly appears.
    print('continue computation')

print('Do something before plotting.')
# Now display plot in a window
make_plot()

answer = input('Back to main and window visible? ')
if answer == 'y':
    print('Excellent')
else:
    print('Nope')

Ответ 3

Я не мог заставить это работать с Canopy (пока не по крайней мере), но я мог бы получить код для запуска вроде как я хотел использовать Geany IDE. Это код, который работает для меня, это очень незначительная модификация первого блока кода в вопросе, где команда show() перемещается выше с конца файла чуть ниже команды make_plot():

from matplotlib.pyplot import plot, draw, show

def make_plot():
    plot([1,2,3])
    draw()
    print 'Plot displayed, waiting for it to be closed.'

print('Do something before plotting.')
# Now display plot in a window
make_plot()
# This line was moved up <----
show()

answer = raw_input('Back to main after plot window closed? ')
if answer == 'y':
    print('Move on')
else:
    print('Nope')

Он не делает точно то, что я хочу, но он достаточно близко: он показывает сюжет пользователю, ждет, пока окно графика не будет закрыто, а затем перейдет к коду. В идеале ему не нужно ждать, пока окно графика не будет закрыто для перехода с кодом, но это лучше, чем ничего, что я думаю.

Код в разделе Добавить 2 выше также работает таким же образом и без изменений, необходимых для Geany, но я предпочитаю этот, потому что он проще. Я обновлю этот ответ If (когда?), Я получаю это, чтобы работать с Canopy.