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

StackOverflow https://stackoverflow.com/questions/458209

  •  19-08-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение

Используйте звонки 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()

Другие советы

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

from matplotlib.pyplot import show, plot

plot(1)  
show(block=False)

# your code

чтобы продолжить свой код.

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

Но если вам нужно более общее решение или если нет другого пути, вы можете запустить все, что блокирует отдельный процесс, используя 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()

Это накладные расходы на запуск нового процесса, а иногда сложнее в отладке в сложных сценариях, поэтому я бы предпочел другое решение (с использованием <= href = "https://stackoverflow.com matplotlib / questions / 458209 / is-there-a-way-detach-matplotlib-plots-so-the-the-computation-can-continue # 458295 "> неблокирующие вызовы API )

Пытаться

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 чтобы переопределить поведение блокировки, описанное выше.

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

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

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

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

<Ол>
  • Использовать block = False внутри шоу: plt.show (block = False)
  • Используйте еще один 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()
    
    <Ч>

    Ну, у меня были большие проблемы с выяснением неблокирующих команд ... Но, наконец, мне удалось переделать " Кулинарная книга / Matplotlib / Анимации - Анимация выбранных элементов графика & Quot; Например, он работает с потоками ( и передает данные между потоками либо через глобальные переменные, либо через многопроцессный 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! 
    

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

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

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

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

    Недостаток:

    • Единственное, о чем я могу думать, это то, что вам придется найти папку и открыть изображение самостоятельно.

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

    plt.show(0)
    

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

    Мне также пришлось добавить 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)
    

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

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

    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 / уголки шкафы-для-мой-ждать-для-пользователя-вход-прерывание-реализация .

    В моей системе 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)
    

    хотя скрипт все еще работал.

    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
    

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

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

    show(block=False)
    draw()
    

    ОП спрашивает об отсоединении matplotlib сюжеты.Большинство ответов предполагают выполнение команд из интерпретатора Python.Представленный здесь вариант использования — это мое предпочтение тестированию кода в терминале (например,bash), где file.py запускается, и вы хотите, чтобы графики отображались, но сценарий 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

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

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top