質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4260閲覧

tkinterのcanvasに一定時間間隔でfigを更新するとき,メモリの消費が激しい。

Deng

総合スコア16

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/04/22 08:45

以下のように、一定時間間隔でグラフを更新したいですが、メモリの消費が激しく、PCが止まりました。
更新する前に、canvasかFigureのクリア方法を教えていただきたい。

Python

1# 一定時間間隔で更新する関数 2def repeat(): 3 """ 4 このは、新しくグラフを更新する。 5 """ 6 now = datetime.now() 7 stime = "更新時間 {0:%Y/%m/%d %H:%M:%S}".format(now) 8 ltext_2.set(stime) 9 fig = plot_wave() 10 canvas = FigureCanvasTkAgg(fig, frame_plot)#canvasに描画します。 11 canvas.get_tk_widget().grid(row=0, column=0) 12 root.after(60000, lambda: repeat()) #60秒間隔で、描画を更新します。```

テスト用の例題コート(実際な膨大データではないので、メモリの消費を見えないです。ご参考のみ)

Python

1# -*- coding: utf-8 -* 2from tkinter import * 3from tkinter import ttk 4import tkinter as tk 5from matplotlib import pyplot as plt 6from matplotlib.backends.backend_tkagg import ( 7 FigureCanvasTkAgg, NavigationToolbar2Tk) 8from datetime import datetime 9 10# 終了関数 11def button_end(): 12 """ 13 終了の動作 14 """ 15 root.quit() 16 root.destroy() 17 18# 時間を取る関数 19def chk_time(root, ltext): 20 """ 21 時間の取り 22 """ 23 now = datetime.now() 24 stime = "{0:%Y/%m/%d %H:%M:%S}".format(now) 25 ltext.set(stime) 26 root.after(5, lambda : chk_time(root, ltext))#時間の進み 27 28# データを処理する関数 29def data(): 30 """ 31 これは、データをファイルから読込ます。 32 この例のため、簡単化しましたが、実際には、何万行のデータを読み、timeとdata_chのリストを形成し、関数data()に渡します。 33 """ 34 time = [] 35 data_ch=[] 36# ここは、例です。 37 for i in range (0,100): 38 time.append(i*0.1) 39 data_ch.append(2.0*i*i+0.5) 40 41 return time, data_ch 42 43# イニシャルプロットをする関数 44def plot_wave_int(): 45 """ 46 これは、canvasの場所を確保するため、イ二シャルfigです。 47 """ 48 # Figureインスタンスを生成する。 49 time=[] 50 data_ch = [] 51 fig = plt.Figure() 52 53 # Axesを作ります 54 55 ax1 = fig.add_subplot(111) 56 ax1.yaxis.set_ticks_position('both') 57 ax1.xaxis.set_ticks_position('both') 58 59 # 軸のラベルを設定する。 60 ax1.set_xlabel('Time, s') 61 ax1.set_ylabel('Rotation number, rpm') 62 63 # データをプロットする。 64 ax1.plot(time, data_ch) 65 66 return fig 67 68 69# プロットをする関数 70def plot_wave(): 71 """ 72 この関数は、data()関数から、timeとdata_chの二つリストを貰い、グラフfigを形成し、figを返します。 73 """ 74 time, data_ch = data() 75 # Figureインスタンスを生成する。 76 fig = plt.Figure() 77 78 # 目盛を内側にする。 79 plt.rcParams['xtick.direction'] = 'in' 80 plt.rcParams['ytick.direction'] = 'in' 81 82 # Axesを作り、グラフの上下左右に目盛線を付ける。 83 84 85 ax1 = fig.add_subplot(111) 86 87 ax1.yaxis.set_ticks_position('left') 88 ax1.xaxis.set_ticks_position('both') 89 90 91 # 軸のラベルを設定する。 92 ax1.set_xlabel('Time, s') 93 ax1.set_ylabel('Rotation number, rpm') 94 95 ax1.plot(time, data_ch) 96 97 return fig 98 99# 更新する関数 100def button_renew(): 101 """ 102 このボタンを押すときに、更新するし、自動更新の時間をリセットする。 103 """ 104 repeat() 105 106# 一定時間間隔で更新する関数 107def repeat(): 108 """ 109 このは、新しくグラフを更新する。 110 """ 111 now = datetime.now() 112 stime = "更新時間 {0:%Y/%m/%d %H:%M:%S}".format(now) 113 ltext_2.set(stime) 114 fig = plot_wave() 115 canvas = FigureCanvasTkAgg(fig, frame_plot)#canvasに描画します。 116 canvas.get_tk_widget().grid(row=0, column=0) 117 root.after(60000, lambda: repeat()) #60秒間隔で、描画を更新します。 118 119 120# Windowの設定 121root = tk.Tk() 122root.title("sample ") 123root.geometry() 124 125# Frameの設定 126frame_repeat = Frame(root, bd=4, relief=GROOVE) 127frame_plot = Frame(root, bd=4, relief=GROOVE) 128frame_now_time = Frame(root) 129frame_repeat_time = Frame(root, bd=4, relief=GROOVE) 130frame_end = Frame(root,bd=5) 131 132# widgetの設定 133btn_renew = Button(frame_repeat, text='更新',fg='green',relief=GROOVE,command=button_renew) 134btn_end = Button(frame_end, text='終了',fg='red',relief=GROOVE, command=button_end) 135 136fig = plot_wave_int() 137canvas = FigureCanvasTkAgg(fig, frame_plot) 138 139ltext = tk.StringVar() 140time_label_now = tk.Label(frame_now_time, textvariable=ltext) 141 142ltext_2 = tk.StringVar() 143time_label_renew= tk.Label(frame_repeat_time, textvariable=ltext_2) 144 145# widgetの配置 146 147frame_repeat.grid(row=0, column=0, sticky=N) 148frame_plot.grid(row=1, column=0) 149frame_now_time.grid(row=3, column=0, sticky=W) 150frame_repeat_time.grid(row=3, column=0, sticky=E) 151frame_end.grid(row=4, column=0, sticky=W + E) 152 153btn_renew.grid(row =0, column = 0,sticky=W + E) 154 155canvas.get_tk_widget().grid(row=0, column=0) 156 157time_label_now.grid() 158time_label_renew.grid() 159 160btn_end.pack() 161 162 163root.after(5, lambda : chk_time(root, ltext))#時間を進みます 164 165 166root.mainloop()

Win10, Python3.8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

問題点:

  • 60秒毎に毎回 FigureCanvasTkAgg を生成し続けてます。

更新する前に、canvasかFigureのクリア方法を教えていただきたい。

オブジェクト生成自体を一度にして、再利用するようにした方が良いです。

解決策:

  • FigureCanvasTkAgg 生成は一度のみにする。
  • fig, ax1 についても同様、生成は一度のみ。
  • 自動更新で呼び出す関数内では、データの中身のみを更新する。

 手順: ax.clear(), ax.plot(...), canvas.draw()

参考:


他の問題点。遭遇されている問題とは異なりますが、

このボタンを押すときに、更新するし、自動更新の時間をリセットする。

リセットせずにタイマーが追加され続けます。

対策:

python

1# 自動更新 ... after() の戻り値を控えておく 2 global timerID 3 timerID = root.after(...) 4 5 6# 更新ボタンでの、自動更新のリセット 7 global timerID 8 if timerID: 9 root.after_cancel(timerID) 10 timerID = None

投稿2021/04/22 18:07

teamikl

総合スコア8664

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Deng

2021/04/22 22:43

teamiklさん 教えていただきまして、ありがとうございました。今すぐ、試してみます。後ほど、効果を報告させていただきます。
Deng

2021/04/22 22:58

効果があることを確認いたしました。勉強になりました。ありがとうございました。
guest

0

plt.close() だけではメモリが解放されない場合がある

を見て、やってみてはいかがでしょうか。
それで効果がないようでしたら、

matplotlib.pyplot のメモリリークの対処法で別プロセスでやる方法もあるようです。

投稿2021/04/22 09:28

ppaul

総合スコア24666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Deng

2021/04/22 22:39

ppaulさん ご回答ありがとうございました。試しましたが、一般なPlotには、効果がありました。しかし、私の場合は、Canvasの中にPlotので、効果は見えないようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問