Есть ли способ отсоединить графики matplotlib, чтобы вычисления могли продолжаться?

python matplotlib plot

204429 просмотра

18 ответа

После этих инструкций в интерпретаторе Python открывается окно с графиком:

from matplotlib.pyplot import *
plot([1,2,3])
show()
# other code

К сожалению, я не знаю, как продолжать интерактивно исследовать фигуру, созданную в show()то время, когда программа выполняет дальнейшие вычисления.

Это вообще возможно? Иногда расчеты являются длинными, и было бы полезно, если бы они продолжались при рассмотрении промежуточных результатов.

Автор: meteore Источник Размещён: 18.08.2019 05:33

Ответы (18)


199 плюса

Решение

Используйте matplotlibзвонки, которые не будут блокировать:

Использование draw():

from matplotlib.pyplot import plot, draw, show
plot([1,2,3])
draw()
print 'continue computation'

# at the end call show to ensure window won't close.
show()

Использование интерактивного режима:

from matplotlib.pyplot import plot, ion, show
ion() # enables interactive mode
plot([1,2,3]) # result shows immediatelly (implicit draw())

print 'continue computation'

# at the end call show to ensure window won't close.
show()
Автор: nosklo Размещён: 19.01.2009 04:52

119 плюса

Используйте ключевое слово «блок», чтобы переопределить поведение блокировки, например

from matplotlib.pyplot import show, plot

plot(1)  
show(block=False)

# your code

продолжить ваш код.

Автор: Jan Размещён: 13.11.2012 01:40

29 плюса

Лучше всегда проверять библиотеку, которую вы используете, поддерживает ли она неблокирующее использование .

Но если вам нужно более общее решение, или если нет другого пути, вы можете запустить все, что блокирует отдельный процесс, используя multprocessingмодуль, включенный в python. Вычисление будет продолжено:

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 'yay'
print 'computation continues...'
print 'that rocks.'

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

То есть накладные расходы на запуск нового процесса, а иногда труднее отлаживать сложные сценарии, так что я предпочел бы другое решение (используя matplotlib«s вызовы Неблокирующего API )

Автор: nosklo Размещён: 19.01.2009 04:40

21 плюса

Пытаться

from matplotlib.pyplot import *
plot([1,2,3])
show(block=False)
# other code
# [...]

# Put
show()
# at the very end of your script
# to make sure Python doesn't bail out
# before you finished examining.

В show()документации сказано:

В неинтерактивном режиме отобразите все фигуры и заблокируйте их, пока фигуры не будут закрыты; в интерактивном режиме это не действует, если рисунки не были созданы до перехода из неинтерактивного в интерактивный режим (не рекомендуется). В этом случае он отображает цифры, но не блокирует.

Один экспериментальный ключевой аргумент, blockможет быть установлен в Trueили Falseдля отмены поведения блокировки, описанного выше.

Автор: Nico Schlömer Размещён: 18.01.2013 11:53

10 плюса

Вы можете прочитать этот документ в matplotlibдокументации под названием:

Использование matplotlib в оболочке Python

Автор: nosklo Размещён: 19.01.2009 05:00

9 плюса

ВАЖНО : Просто чтобы прояснить что-то. Я предполагаю, что команды находятся внутри .pyскрипта, и скрипт вызывается с помощью, например, python script.pyиз консоли.

Простой способ, который работает для меня:

  1. Используйте block = False внутри show: plt.show (block = False)
  2. Используйте другой show () в конце скрипта .py.

Пример script.py файла:

plt.imshow(*something*)                                                               
plt.colorbar()                                                                             
plt.xlabel("true ")                                                                   
plt.ylabel("predicted ")                                                              
plt.title(" the matrix")  

# Add block = False                                           
plt.show(block = False)

################################
# OTHER CALCULATIONS AND CODE HERE ! ! !
################################

# the next command is the last line of my script
plt.show()

Автор: serafeim Размещён: 08.03.2017 02:37

8 плюса

В моем случае я хотел, чтобы несколько окон всплыли во время их вычисления. Для справки это так:

from matplotlib.pyplot import draw, figure, show
f1, f2 = figure(), figure()
af1 = f1.add_subplot(111)
af2 = f2.add_subplot(111)
af1.plot([1,2,3])
af2.plot([6,5,4])
draw() 
print 'continuing computation'
show()

PS. Очень полезное руководство по OO-интерфейсу matplotlib .

Автор: meteore Размещён: 21.01.2009 02:05

6 плюса

Ну, у меня были большие проблемы с выяснением неблокирующих команд ... Но, наконец, мне удалось переработать пример " Cookbook / Matplotlib / Animations - Animating selected plot elements ", чтобы он работал с потоками ( и передавал данные между потоками либо через глобальные переменные или через мультипроцессPipe ) в Python 2.6.5 в Ubuntu 10.04.

Сценарий можно найти здесь: Animating_selected_plot_elements-thread.py - в противном случае вставляется ниже ( с меньшим количеством комментариев ) для справки:

import sys
import gtk, gobject
import matplotlib
matplotlib.use('GTKAgg')
import pylab as p
import numpy as nx 
import time

import threading 



ax = p.subplot(111)
canvas = ax.figure.canvas

# for profiling
tstart = time.time()

# create the initial line
x = nx.arange(0,2*nx.pi,0.01)
line, = ax.plot(x, nx.sin(x), animated=True)

# save the clean slate background -- everything but the animated line
# is drawn and saved in the pixel buffer background
background = canvas.copy_from_bbox(ax.bbox)


# just a plain global var to pass data (from main, to plot update thread)
global mypass

# http://docs.python.org/library/multiprocessing.html#pipes-and-queues
from multiprocessing import Pipe
global pipe1main, pipe1upd
pipe1main, pipe1upd = Pipe()


# the kind of processing we might want to do in a main() function,
# will now be done in a "main thread" - so it can run in
# parallel with gobject.idle_add(update_line)
def threadMainTest():
    global mypass
    global runthread
    global pipe1main

    print "tt"

    interncount = 1

    while runthread: 
        mypass += 1
        if mypass > 100: # start "speeding up" animation, only after 100 counts have passed
            interncount *= 1.03
        pipe1main.send(interncount)
        time.sleep(0.01)
    return


# main plot / GUI update
def update_line(*args):
    global mypass
    global t0
    global runthread
    global pipe1upd

    if not runthread:
        return False 

    if pipe1upd.poll(): # check first if there is anything to receive
        myinterncount = pipe1upd.recv()

    update_line.cnt = mypass

    # restore the clean slate background
    canvas.restore_region(background)
    # update the data
    line.set_ydata(nx.sin(x+(update_line.cnt+myinterncount)/10.0))
    # just draw the animated artist
    ax.draw_artist(line)
    # just redraw the axes rectangle
    canvas.blit(ax.bbox)

    if update_line.cnt>=500:
        # print the timing info and quit
        print 'FPS:' , update_line.cnt/(time.time()-tstart)

        runthread=0
        t0.join(1)   
        print "exiting"
        sys.exit(0)

    return True



global runthread

update_line.cnt = 0
mypass = 0

runthread=1

gobject.idle_add(update_line)

global t0
t0 = threading.Thread(target=threadMainTest)
t0.start() 

# start the graphics update thread
p.show()

print "out" # will never print - show() blocks indefinitely! 

Надеюсь, это поможет кому-то,
ура!

Автор: sdaau Размещён: 10.11.2010 09:55

5 плюса

Во многих случаях удобнее сохранить изображение в формате .png на жестком диске. Вот почему:

Преимущества:

  • Вы можете открыть его, взглянуть на него и закрыть в любое время в процессе. Это особенно удобно, когда ваше приложение работает долго.
  • Ничего не всплывает, и вы не обязаны открывать окна. Это особенно удобно, когда вы имеете дело со многими фигурами.
  • Ваше изображение доступно для дальнейшего использования и не теряется при закрытии окна рисунка.

Минус:

  • Единственное, о чем я могу думать, - это то, что вам придется пойти и найти папку и открыть изображение самостоятельно.
Автор: elgehelge Размещён: 18.12.2013 06:21

5 плюса

Если вы работаете в консоли, то есть IPythonвы можете использовать, plt.show(block=False)как указано в других ответах. Но если вы ленивы, вы можете просто набрать:

plt.show(0)

Который будет таким же.

Автор: Anton Protopopov Размещён: 18.01.2016 11:11

4 плюса

Мне также пришлось добавить plt.pause(0.001)в мой код, чтобы он действительно работал внутри цикла for (иначе он будет показывать только первый и последний график):

import matplotlib.pyplot as plt

plt.scatter([0], [1])
plt.draw()
plt.show(block=False)

for i in range(10):
    plt.scatter([i], [i+1])
    plt.draw()
    plt.pause(0.001)
Автор: Martin Pecka Размещён: 09.11.2016 02:16

3 плюса

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

Это, вероятно, слишком нестандартно и не рекомендуется для производственного кода. В этом коде, вероятно, много скрытых ошибок.

from contextlib import contextmanager

@contextmanager
def keep_plots_open(keep_show_open_on_exit=True, even_when_error=True):
    '''
    To continue excecuting code when plt.show() is called
    and keep the plot on displaying before this contex manager exits
    (even if an error caused the exit).
    '''
    import matplotlib.pyplot
    show_original = matplotlib.pyplot.show
    def show_replacement(*args, **kwargs):
        kwargs['block'] = False
        show_original(*args, **kwargs)
    matplotlib.pyplot.show = show_replacement

    pylab_exists = True
    try:
        import pylab
    except ImportError: 
        pylab_exists = False
    if pylab_exists:
        pylab.show = show_replacement

    try:
        yield
    except Exception, err:
        if keep_show_open_on_exit and even_when_error:
            print "*********************************************"
            print "Error early edition while waiting for show():" 
            print "*********************************************"
            import traceback
            print traceback.format_exc()
            show_original()
            print "*********************************************"
            raise
    finally:
        matplotlib.pyplot.show = show_original
        if pylab_exists:
            pylab.show = show_original
    if keep_show_open_on_exit:
        show_original()

# ***********************
# Running example
# ***********************
import pylab as pl
import time
if __name__ == '__main__':
    with keep_plots_open():
        pl.figure('a')
        pl.plot([1,2,3], [4,5,6])     
        pl.plot([3,2,1], [4,5,6])
        pl.show()

        pl.figure('b')
        pl.plot([1,2,3], [4,5,6])
        pl.show()

        time.sleep(1)
        print '...'
        time.sleep(1)
        print '...'
        time.sleep(1)
        print '...'
        this_will_surely_cause_an_error

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

Я могу использовать что-то вроде вопроса об истечении времени ожидания «Конец сценария! \ NНажмите p, если вы хотите приостановить вывод печати (у вас есть 5 секунд):» по адресу https://stackoverflow.com/questions/26704840/corner -cases-for-my-wait-for-user-прерывание-ввода-реализации .

Автор: Simon Streicher Размещён: 04.11.2014 12:14

2 плюса

В моей системе show () не блокируется, хотя я хотел, чтобы скрипт ждал, пока пользователь не будет взаимодействовать с графиком (и собирает данные с помощью обратных вызовов 'pick_event'), прежде чем продолжить.

Чтобы заблокировать выполнение до закрытия окна графика, я использовал следующее:

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(x,y)

# set processing to continue when window closed
def onclose(event):
    fig.canvas.stop_event_loop()
fig.canvas.mpl_connect('close_event', onclose)

fig.show() # this call does not block on my system
fig.canvas.start_event_loop_default() # block here until window closed

# continue with further processing, perhaps using result from callbacks

Однако обратите внимание, что canvas.start_event_loop_default () выдает следующее предупреждение:

C:\Python26\lib\site-packages\matplotlib\backend_bases.py:2051: DeprecationWarning: Using default event loop until function specific to this GUI is implemented
  warnings.warn(str,DeprecationWarning)

хотя сценарий все еще выполняется.

Автор: Andrew Размещён: 17.03.2011 05:06

2 плюса

plt.figure(1)
plt.imshow(your_first_image)

plt.figure(2)
plt.imshow(your_second_image)

plt.show(block=False) # That's important 

raw_input("Press ENTER to exist") # Useful when you run your Python script from the terminal and you want to hold the running to see your figures until you press Enter
Автор: thanhtang Размещён: 21.02.2017 06:27

1 плюс

На мой взгляд, ответы в этой теме предоставляют методы, которые не работают для каждой системы и в более сложных ситуациях, таких как анимация. Я предлагаю взглянуть на ответ MiKTeX в следующей ветке, где найден надежный метод: как ждать, пока закончится анимация matplotlib?

Автор: MikeTeX Размещён: 27.12.2015 06:17

0 плюса

Если вы хотите открыть несколько фигур, оставив их открытыми, этот код работает для меня:

show(block=False)
draw()
Автор: DomDev Размещён: 16.09.2016 03:11

0 плюса

ОП спрашивает об отстранении matplotlibучастков. Большинство ответов предполагают выполнение команды из интерпретатора Python. Представленный здесь вариант использования - это мое предпочтение для тестирования кода в терминале (например, bash), где file.pyзапускается a, и вы хотите, чтобы появлялись графики, а скрипт python завершался и возвращался в командную строку.

Этот автономный файл используется multiprocessingдля запуска отдельного процесса отображения данных с помощью matplotlib. Основная ветка выходит с использованием os._exit(1)упомянутого в этом посте. В os._exit()силах основные для выхода , но оставляют matplotlibдочерний процесс живой и отзывчивые , пока окно участка не будет закрыто. Это отдельный процесс полностью.

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

multiprocessingпредназначен для выполнения кода только на Python, что делает его, возможно, лучше, чем subprocess. multiprocessingявляется кроссплатформенным, так что это должно хорошо работать в Windows или Mac без каких-либо настроек. Нет необходимости проверять основную операционную систему. Это было проверено на Linux, Ubuntu 18.04LTS.

#!/usr/bin/python3

import time
import multiprocessing
import os

def plot_graph(data):
    from matplotlib.pyplot import plot, draw, show
    print("entered plot_graph()")
    plot(data)
    show() # this will block and remain a viable process as long as the figure window is open
    print("exiting plot_graph() process")

if __name__ == "__main__":
    print("starting __main__")
    multiprocessing.Process(target=plot_graph, args=([1, 2, 3],)).start()
    time.sleep(5)
    print("exiting main")
    os._exit(0) # this exits immediately with no cleanup or buffer flushing

При запуске file.pyоткрывается окно с рисунком, затем оно __main__закрывается, но окно с рисунком multiprocessing+ matplotlibреагирует на кнопки масштабирования, панорамирования и других операций, поскольку это независимый процесс.

Проверьте процессы в командной строке bash:

ps ax|grep -v grep |grep file.py

Автор: Marc Compere Размещён: 11.07.2019 05:43

0 плюса

Используйте plt.show(block=False)и в конце вашего сценария вызова plt.show().

Это гарантирует, что окно не будет закрыто после завершения скрипта.

Автор: Ken Mueller Размещён: 18.08.2019 02:25
Вопросы из категории :
32x32