2012-04-30 71 views
4

我有一個渲染的圖表需要3秒,然後可以從上圖中添加事物的子圖表添加到它。我想緩存主圖表中的座標軸,以便在繪製子圖時可以檢索並修改它。我怎麼能通過這個錯誤?緩存帶Memcache的Matplotlib(不會醃汁)

繼承人的樣本測試代碼:

import pylibmc 
cache = pylibmc.Client(["127.0.0.1"], binary=True, behaviors={"tcp_nodelay": True, "ketama": True}) 
import matplotlib.pyplot as plt 


cache_name = 'test' 
fig = plt.figure(figsize=(20, 7)) 
ax = fig.add_axes([0, 0.15, 0.98, 0.85]) 
cache.set(cache_name, ax, 300) 

其中提供了以下錯誤:

cPickle.PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed 

有反正我能得到這個工作?

+1

數據結構是否需要3秒或matplotlib的實際繪圖?之前已經有過關於這個的討論,而且在製作matplotlib可序列化方面顯然沒有做過任何事情。 – jdi

+0

Matplotlib繪圖。由於他們燭臺的陰謀詭計,我正在繪製使用單個條形圖的燭臺圖表。而且由於我不能通過列表工作(比較顏色,值,錯誤欄),所以我通過一個循環(大約400個項目)單獨添加每個欄,這很可能導致它花費很長時間。示例腳本在這裏:http://pastebin.com/6aD8YZfM。如果我能夠緩存那些最終的小節,時間就不那麼重要了。 – NoviceCoding

+0

那麼在那個示例循環中,軸創建需要時間?你做了400次,產生一個需要3秒鐘的軸的集合? – jdi

回答

3

有關於matplotlib數字的願望能夠被序列化的討論。我還沒有看到任何報道這個問題已被解決甚至被接受爲目標。所以如果你試圖通過線路發送給memcached,它顯然會失敗。我在搜索時發現的討論表明,matplotlib的當前設計不容易滿足這個目標,並且需要對內部進行重構。參考:http://old.nabble.com/matplotlib-figure-serialization-td28016714.html

你可以做什麼,以大幅度減少執行時間,就是將數據重新組織到數據集中,並且只調用一次ax.bar()。然後可以將數據集序列化並以您想要的任何格式存儲(例如,在memcached中)。

下面是一個代碼示例,顯示您的方法和將它們組合成數據集的方法之間的測試。您可以更輕鬆,如果你想在這裏查看:https://gist.github.com/2597804

import matplotlib.pyplot as plt 
from random import randint 
from time import time 

DATA = [ 
    (i, randint(5,30), randint(5,30), randint(30,35), randint(1,5)) \ 
    for i in xrange(1, 401) 
] 

def mapValues(group): 
    ind, open_, close, high, low = group 
    if open_ > close: # if open is higher then close 
     height = open_ - close # heigth is drawn at bottom+height 
     bottom = close 
     yerr = (open_ - low, high - open_) 
     color = 'r' # plot as a white barr 
    else: 
     height = close - open_ # heigth is drawn at bottom+height 
     bottom = open_ 
     yerr = (close - low, high - close) 
     color = 'g' # plot as a black bar 

    return (ind, height, bottom, yerr, color) 

# 
# Test 1 
# 
def test1(): 
    fig = plt.figure() 
    ax = fig.add_subplot(111) 

    data = map(mapValues, DATA) 

    start = time() 

    for group in data: 

     ind, height, bottom, yerr, color = group 

     ax.bar(left=ind, height=height, bottom=bottom, yerr=zip(yerr), 
       color=color, ecolor='k', zorder=10, 
       error_kw={'barsabove': False, 'zorder': 0, 'capsize': 0}, 
       alpha=1) 

    return time()-start 

# 
# Test 2 
# 
def test2(): 
    fig = plt.figure() 
    ax = fig.add_subplot(111) 

    # plotData can be serialized 
    plotData = zip(*map(mapValues, DATA)) 

    ind, height, bottom, yerr, color = plotData 

    start = time() 

    ax.bar(left=ind, height=height, bottom=bottom, yerr=zip(*yerr), 
      color=color, ecolor='k', zorder=10, 
      error_kw={'barsabove': False, 'zorder': 0, 'capsize': 0}, 
      alpha=1) 

    return time()-start 


def doTest(fn): 
    end = fn() 
    print "%s - Sec: %0.3f, ms: %0d" % (fn.__name__, end, end*1000) 



if __name__ == "__main__": 
    doTest(test1) 
    doTest(test2) 

    # plt.show() 

結果:

python plot.py 
test1 - Sec: 1.592, ms: 1592 
test2 - Sec: 0.358, ms: 357 
+0

謝謝一堆。製圖從5秒到1.7秒非常感謝!仍然希望長期使用matplotlib緩存機制! – NoviceCoding

-1

看着documentation,看起來fig.add_axes()將一個元組作爲參數傳遞給列表。因此,它不會返回Axes對象(因爲它沒有被創建),所以ax被賦值給函數本身。

+1

這是不正確的。各種方法可以採取一個序列,無論是列表還是元組。無論哪種方式。 'add_axes()'返回一個'Axis'對象。問題在於OP試圖通過線路將Axis實例發送到memcached,它希望能夠序列化對象。 matplotlib對象不能被序列化。它基本上窒息了各軸的內部。看看'ax .__ dict__'的價值。你會看到它的其他matplotlib對象,包括圖等巨大的參考。 – jdi

1

至於matplotlib 1.2的你應該可以鹹菜和unpickle數字。

這是非常的「實驗性」的特徵,但如果你發現任何問題,請讓我們知道MPL郵件列表或者通過github.com/matplotlib/matplotlib提出問題

HTH