円グラフを使用して統計をグラフ化するために複数の SVG イメージを作成する予定の Python Pyramid アプリケーションを開発しています。私のテストでは、1 つの SVG ビューが正しく機能し、2 番目の SVG 出力ビューを追加するとすぐに、2 番目の SVG 画像が読み込まれることがわかりました (SVG 画像の読み込み順序は関係ありません)。このビューを参照する別のビューでは、SVG ファイルをロードするためのその他の呼び出しで SVG イメージが「結合」されます。これは、メモリが適切にクリアされていないように見えるため、Python スタックのどこかにバグがあるようです (主に複数の SVG ファイルの場合、以下の詳細を参照してください)。また、十分な数の画像/ページがロードされると、TclError が発生することにも注意してください。
私はより多くのビューを持つより詳細なアプリケーションで SVG を使用していたので、最小化/縮小されたアプリケーションでこれを再現して、それが私が行っている特別なことではなく、このコードが Pyramid alchemyテンプレートとデータベースから直接生成されていることを示しています。通話は関係ありません。このデータベースは、詳細アプリケーションで積極的に利用されています。このアプリケーションには 3 つのビューしかありません。最初のビューは元のテンプレートの一部です。また、DEBUG ロギングを追加して、他の SVG ビューの内部呼び出しがあることを示す兆候がないことを明確にしています。
一部のビュー コードは、文字列としての Matplotlib svg に基づいており、主にStringIO
. 円グラフが必要であるため、それが私のコードが参照されている質問のコードと異なる主な理由であることに注意してください。StringIO
を使用してもを使用しても、問題は本質的に同じであることがわかりましたcStringIO
。私のコードでは、cStringIO
.
完全なアプリケーション コードは、https ://github.com/danielpronych/pyramidapp で入手できます。
PyPlot ドキュメンテーション:: pyplot api
更新: 最初の SVG ビューからのコード (図のハンドルと閉じるコマンド):
@view_config(route_name='view_test_svg')
def test_svg_view(request):
# Full module import is not allowed by Pyramid
#from pylab import *
# Do individual required imports instead
from pylab import close, figure, axes, pie, title, savefig
# For clarity, note that the above, and below, function the same
#from matplotlib.pyplot import close, figure, axes, pie, title, savefig
log.debug('In test_svg_view')
fig = figure(1, figsize=(6,6))
ax = axes([0.1, 0.1, 0.8, 0.8])
labels = ['Frogs', 'Hogs', 'Dogs', 'Logs']
fracs = [15, 30, 45, 10]
explode=(0, 0.05, 0, 0)
pie(fracs, explode=explode, labels=labels,
autopct='%1.1f%%', shadow=True, startangle=90)
title('Raining Hogs and Dogs', bbox={'facecolor':'0.8', 'pad':5})
imgdata = cStringIO.StringIO()
fig.savefig(imgdata, format='svg')
imgdata.seek(0)
svg_dta = imgdata.getvalue()
# Close the StringIO buffer
imgdata.close()
close('all')
return Response(svg_dta, content_type='image/svg+xml')
このコードの手順:
- http://localhost:6543/test.svg を読み込む
- http://localhost:6543/test2.svg を読み込む
- (1)または(2)のいずれかを再度ロードしてください。
pserve
コマンドウィンドウからの兆候なしに連続して「スピン」するのはなぜですか。
注:このコードで同じ SVG ビューを 3 回ロードすると、上記の手順と同じ結果になりますが、以下のコードでは発生しません。
また、pyplot パイにはリターンがあることに注意してください。ただし、それ自体は「ハンドル」ではありません。
pserve
1分以上待っても(特に上記の手順を実行した後)、ウィンドウがControl + Cコマンドに応答しません。
最初の SVG ビューからのコード (オリジナル、以下の手順はこのコードからのもの):
@view_config(route_name='view_test_svg')
def test_svg_view(request):
# Full module import is not allowed by Pyramid
#from pylab import *
# Do individual required imports instead
from pylab import figure, axes, pie, title, savefig
# For clarity, note that the above, and below, function the same
#from matplotlib.pyplot import figure, axes, pie, title, savefig
log.debug('In test_svg_view')
figure(1, figsize=(6,6))
ax = axes([0.1, 0.1, 0.8, 0.8])
labels = ['Frogs', 'Hogs', 'Dogs', 'Logs']
fracs = [15, 30, 45, 10]
explode=(0, 0.05, 0, 0)
pie(fracs, explode=explode, labels=labels,
autopct='%1.1f%%', shadow=True, startangle=90)
title('Raining Hogs and Dogs', bbox={'facecolor':'0.8', 'pad':5})
imgdata = cStringIO.StringIO()
savefig(imgdata, format='svg')
imgdata.seek(0)
svg_dta = imgdata.getvalue()
# Close the StringIO buffer
imgdata.close()
return Response(svg_dta, content_type='image/svg+xml')
Python バージョン: Python 2.7.5
Python パッケージの構成 (プライマリ パッケージのみ)
- ピラミッド-1.6a1-py2.7
- matplotlib-1.4.3-py2.7-win32
再現するために取られた手順:
- ピラミッドアプリを保存します。
指示:pserve development.ini --reload
Starting server in PID 4912.
serving on http://0.0.0.0:6543
これは正しく機能することに注意してください
DEBUG [pyramidapp.views:22][Dummy-2] In test_svg_view
これにより、両方の SVG ファイルが「結合」されることに注意してください。
DEBUG [pyramidapp.views:45][Dummy-3] In test2_svg_view
これは test2.svg とまったく同じように機能することに注意してください。タイトルも同じで、同じ長さであり、画像もこのビューで結合されます。
DEBUG [pyramidapp.views:22][Dummy-4] In test_svg_view
今回は test.svg の前にこのビューがロードされたため、これは最初のロードで適切に機能することに注意してください。
DEBUG [pyramidapp.views:45][Dummy-2] In test2_svg_view
Control+C を使用して pserve プロセスを終了したときのトレースログ
Error in sys.exitfunc:
Traceback (most recent call last):
File "--python_path--\lib\atexit.py", line 24, in _run_exitfuncs
func(*targs, **kargs)
File "--python_path--\lib\site-packages\matplotlib-1.4.3-py2.7-win32.egg\ma
tplotlib\_pylab_helpers.py", line 89, in destroy_all
manager.destroy()
File "--python_path--\lib\site-packages\matplotlib-1.4.3-py2.7-win32.egg\ma
tplotlib\backends\backend_tkagg.py", line 588, in destroy
self.window.destroy()
File "--python_path--\lib\lib-tk\Tkinter.py", line 1789, in destroy
for c in self.children.values(): c.destroy()
File "--python_path--\lib\lib-tk\Tkinter.py", line 2042, in destroy
self.tk.call('destroy', self._w)
_tkinter.TclError: out of stack space (infinite loop?)
^C caught in monitor process
重要: SVG 画像が十分に読み込まれると、次のようになります。
現在これを修正する唯一の方法は、再起動することpserve
です。my_view
また、SVG 画像がそのようなビューによって参照または利用されない限り、ロードなどのビューが適切に読み込まれることにも注意してください。
もう 1 つの重要な注意点は、SVG ファイルが 1 つだけ、つまりhttp://localhost:6543/test.svgが常にロードされているpserve
限り、明らかな問題なしにイメージを (潜在的に) 無限に再ロード/更新できるように見えることです。または以下に遭遇:
_tkinter.TclError
TclError: out of stack space (infinite loop?)
Traceback (most recent call last)
File "--python_path--\lib\site-packages\pyramid_debugtoolbar-2.0.2-py2.7.egg\pyramid_debugtoolbar\panels
\performance.py", line 69, in noresource_timer_handler
Display the sourcecode for this frameOpen an interactive python shell in this frameresult = handler(request)
File "--python_path--\lib\site-packages\pyramid-1.6a1-py2.7.egg\pyramid\tweens.py", line 20, in excview_tween
Display the sourcecode for this frameOpen an interactive python shell in this frameresponse = handler(request)
File "--python_path--\lib\site-packages\pyramid_tm-0.11-py2.7.egg\pyramid_tm\__init__.py", line 94, in tm_tween
Display the sourcecode for this frameOpen an interactive python shell in this framereraise(*exc_info)
File "--python_path--\lib\site-packages\pyramid_tm-0.11-py2.7.egg\pyramid_tm\__init__.py", line 75, in tm_tween
Display the sourcecode for this frameOpen an interactive python shell in this frameresponse = handler(request)
File "--python_path--\lib\site-packages\pyramid-1.6a1-py2.7.egg\pyramid\router.py", line 145, in handle_request
Display the sourcecode for this frameOpen an interactive python shell in this frameview_name
File "--python_path--\lib\site-packages\pyramid-1.6a1-py2.7.egg\pyramid\view.py", line 527, in _call_view
Display the sourcecode for this frameOpen an interactive python shell in this frameresponse = view_callable
(context, request)
File "--python_path--\lib\site-packages\pyramid-1.6a1-py2.7.egg\pyramid\config\views.py", line 384, in
viewresult_to_response
Display the sourcecode for this frameOpen an interactive python shell in this frameresult = view(context,
request)
File "--python_path--\lib\site-packages\pyramid-1.6a1-py2.7.egg\pyramid\config\views.py", line 506, in
_requestonly_view
Display the sourcecode for this frameOpen an interactive python shell in this frameresponse = view(request)
File "c:\projects\python\pyramid\pyramidapp\pyramidapp\views.py", line 55, in test2_svg_view
Display the sourcecode for this frameOpen an interactive python shell in this framesavefig(imgdata,
format='svg')
File "--python_path--\lib\site-packages\matplotlib-1.4.3-py2.7-win32.egg\matplotlib\pyplot.py", line 578, in
savefig
Display the sourcecode for this frameOpen an interactive python shell in this framedraw() # need this if
'transparent=True' to reset colors
File "--python_path--\lib\site-packages\matplotlib-1.4.3-py2.7-win32.egg\matplotlib\pyplot.py", line 571, in
draw
Display the sourcecode for this frameOpen an interactive python shell in this frameget_current_fig_manager
().canvas.draw()
File "--python_path--\lib\site-packages\matplotlib-1.4.3-py2.7-win32.egg\matplotlib\backends\backend_tkagg.py",
line 350, in draw
Display the sourcecode for this frameOpen an interactive python shell in this frametkagg.blit(self._tkphoto,
self.renderer._renderer, colormode=2)
File "--python_path--\lib\site-packages\matplotlib-1.4.3-py2.7-win32.egg\matplotlib\backends\tkagg.py", line
24, in blit
Display the sourcecode for this frameOpen an interactive python shell in this frametk.call("PyAggImagePhoto",
photoimage, id(aggimage), colormode, id(bbox_array))
TclError: out of stack space (infinite loop?)
更新 (2015 年 9 月): Sergey からのさらなる更新を期待していました。しかし、彼の解決策では問題は解決されませんでした。かなりの時間を待っても何も起こらなかったため、私の解決策だけが実際にこの問題を解決したことがわかりました。最後に、明確にするために、この問題はバッチ処理でも表面化するため、私のソリューションは Web ベースの実装とバッチ処理で機能します。