2011-09-29 129 views
1

問題同時使用線程/多處理器

我寫一個程序,讀取了一組從語料庫文件(每行一個文件)如何使用簡單的SQLAlchemy電話。使用功能processdocument處理每個文檔,分配一個唯一的ID,然後寫入數據庫。理想情況下,我們希望使用多個流程來完成此操作。邏輯如下:

  1. 主例程創建一個新的數據庫並設置一些表。
  2. 主例程設置一組進程/線程將運行一個輔助函數。
  3. 主例程啓動所有進程。
  4. 主例程讀取語料庫,將文檔添加到隊列中。
  5. 每個進程的工作函數循環,從隊列中讀取文檔,使用processdocument從中提取信息,並將信息寫入數據庫表中的新條目。
  6. 一旦隊列爲空並且主例程設置了相應的標誌(一旦沒有更多文檔添加到隊列中),工作程序就會中斷。

問題

我是比較新的SQLAlchemy的(和數據庫一般)。我認爲用於在主例程中設置數據庫的代碼工作正常,從我可以告訴的。我被卡住的地方是我不確定如何將每個進程的工作者函數寫入數據庫而不與其他人衝突。

沒有什麼特別複雜的事情發生:每個進程都獲得一個唯一的值,以便從受Lock保護的multiprocessing.Value對象分配給一個條目。如果有的話,我只是不確定是否應該傳遞給工作函數(除隊列外)。我是否會傳遞我在主例程中創建的sqlalchemy.Engine實例?元數據實例?我是否爲每個流程創建一個新的引擎?有沒有其他規範的方式來做到這一點?我需要記住一些特別的東西嗎?

附加評論

我很清楚我能不能與多費心,但在一個單一的過程中做到這一點,但我會寫出具有幾個進程讀取數據庫後代碼在,所以我不妨想出如何做到這一點。

在此先感謝您的幫助!

回答

4

MetaData及其Table對象的集合應該被視爲應用程序的固定的,不可變的結構,與您的函數和類定義不同。正如你在分叉子進程時所知道的那樣,你的應用程序的所有模塊級結構仍然存在於進程邊界之內,而表的defs通常在這個類別中。

然而,引擎是指一個DBAPI連接池,通常是TCP/IP連接,有時也是文件句柄。 DBAPI連接本身通常不能在子進程邊界上移植,因此您希望爲每個子進程創建一個新的Engine,或者使用非池化引擎,這意味着您使用的是NullPool。

你也不應該做任何形式的MetaData與引擎的關聯,即「綁定」元數據。這種做法雖然在各種過時的教程和博客文章中很突出,但實際上並不是一個通用目的,我儘可能不去強調這種工作方式。

如果您使用的是ORM,則存在類似於「程序結構/活動工作」的二分法,您的映射類當然是在所有子進程之間共享的,但您肯定希望Session對象對於特定子進程是本地的 - 這些對應於一個實際的DBAPI連接以及大量的其他可變狀態,這些狀態最好保存在操作本地。

+0

您可能想要提到的是,在OP決定使用線程而不是進程的情況下,會話對象不是線程安全的。整個「提交」操作很大程度上取決於在提交期間對象是不可變的。 – patrys

+0

感謝您的回覆,但您可能需要更詳細地解釋此問題。讓我們假裝,爲了爭辯,我真的很愚蠢,不明白這裏使用的大部分詞彙......我不知道我是否正確理解這一點:我不需要做任何特別的事情所有?不要將Table實例作爲參數傳遞給worker函數,只需添加並提交即可? –

+0

我沒有使用ORM,因爲我還沒有真正想出詳細的工作方式(對於所有這些都很新穎),但是我可能需要,因爲我基本上正在處理兩個表格,並且在ManytoMany關係中有行。這需要使用ORM,對吧? –