2011-06-24 111 views
1

我有這種情況:Python多線程

用Zope/Plone和一些mine python API創建的網頁。有一個網頁,稱之爲「a」,通過python方法調用一個數據庫(Postgres)並返回一些信息。在頁面「a」上,你可以修改數據庫數據「離線」(我打算修改不是立即寫入數據庫,而是在你按下「保存」並調用python API方法後的第二個時刻)。所以,想象一下這種情況:一個名爲「Sam」的用戶加載頁面並開始修改數據。同時,名爲「Sara」的用戶通過頁面「a」點擊「保存」修改數據庫。現在,Sam沒有實際的數據庫數據:他會推「保存」並覆蓋Sara的數據更改。

我會在我的網頁上實時發出提醒。我以爲我可以做這樣的事情:

做一個AJAX調用,這是不可阻擋的,並繼續與頁面呈現。 AJAX調用一個python方法創建一個無限循環的線程(在「X」條件下)。當我在數據庫上寫入數據時,我會調用一個函數來改變「X條件」,停止線程並返回AJAX。

此外,我不能鎖定數據庫,因爲我必須免費訪問每個想要修改我的數據庫的用戶。

我的問題是:如何識別python線程?我剛剛看到,從Thread繼承的類上的每個方法都需要「self」作爲參數。此外,當我訪問「a」頁面時,我必須調用該線程,這將在代碼中的某處(例如在「threads」模塊中),但插入位於另一個模塊上。那麼,我怎樣才能實現我的想法?

如果有人有另外一個設想,告訴我沒有任何問題:)

回答

3

的你討論問題的領域通常被稱爲「併發」。由於您的方法會在目標項目中的任何字段更改時警告或阻止用戶更新,因此此方法通常稱爲「悲觀併發」。做到這一點的一種方式是跟蹤項目被選擇時的樣子,並且只有在數據庫版本看起來與您選擇的版本或自某個時間以來沒有更新過的版本完全一樣時纔會更新(時間戳字段可能有幫助)。您還可以嘗試樂觀併發性,其中只檢查一個用戶已更新並保存回數據存儲的字段未由其他用戶更新。如果您選擇支持併發的ORM庫,這兩種方法都是最簡單的。

我最喜歡的python網絡庫是django,這裏是關於你想要解決的相同情況的SO問題:Django: How can I protect against concurrent modification of database entries。我希望它有幫助。

以您建議的方式處理併發性是可行的,但在大多數情況下應該避免。在爲具有廣泛副作用並且沒有統一數據訪問的複雜對象(在系統的整個生命週期中存在大約5種數據訪問方法,這是一個多彩的系統)的大型系統中添加併發性之前,我已經做到了這一點。這是容易出錯並且處理併發性的複雜方式(我認爲我有一個客戶端應用程序,並在將數據表中的項標記爲「簽出」後啓動了一個觀察器線程,該數據表描述了對象的類型和標識符,檢查出它的用戶,當他們檢查出它時,以及它在多長時間內是有效的,以防在檢查完對象時檢查對象的客戶端無法檢查它)。

如果設置爲不使用ORM並在發生對項目發生更改時向用戶顯示消息,請嘗試關閉上次更新的時間戳列,並讓您​​的ajax調用檢查以查看上次更新時間比第一次加載物品時要大。所以,如果你編寫一個通用的方法來做到這一點,你只需要表名,主鍵和時間戳。

Web服務方法可能如下:

def is_most_current(table_name, id): 
    db = MySQLdb.connect(passwd="moonpie",db="thangs") 
    c=db.cursor() 
    c.execute("SELECT last_updated from %s where id = %s", (table_name, id)) 
    return c.fetchone() 

至於蟒蛇的多線程庫,Python的線程是混亂和生產性能得益於差的問題與Python的全球連鎖,你實際上可能要產生新的進程中很多情況下(多處理庫相當,並行處理場景下性能更好)。就「自我」而言,這是一種Python引用你所處理的類的實例的pythonic慣例,很像C語言中的「this」。當你構造一個線程時,你可以通過給它一個唯一的名字來輕鬆識別它。有關更多信息,請參閱multiprocessingthreading文檔。如果你可以避免這個問題的線程,我建議你這樣做。

+0

你的回答很好,但我想告訴用戶,在某個istant中,當他打開「a」頁面時,另一個用戶更新數據庫。然後以propoer的方式更改字段(在「a」頁面) – DonCallisto

+0

更新了我的答案,當我收到您的評論時,仍然鍵入最後幾段。 – marr75