- 基於.NET-A的應用服務器(Wonderware IAS/System Platform)託管該工廠車間與各種設備進行通信的自動化對象。
- CPython位於此應用程序服務器內部(使用Python for .NET)。
- 自動化對象具有內置的腳本功能(使用基於.NET的自定義語言)。這些腳本調用Python函數。
Python函數是系統的一部分,用於跟蹤工廠車間的工作進度。系統的目的是跟蹤流程中生成的小部件,確保小部件按照正確的順序遍歷整個過程,並檢查過程中是否滿足某些條件。小部件生產歷史和小部件狀態存儲在關係數據庫中,這是SQLAlchemy發揮其作用的地方。
例如,當某個微件通過掃描儀,自動化軟件觸發以下腳本(寫在應用程序服務器的自定義腳本語言):
' wiget_id and scanner_id provided by automation object
' ExecFunction() takes care of calling a CPython function
retval = ExecFunction("WidgetScanned", widget_id, scanner_id);
' if the python function raises an Exception, ErrorOccured will be true
' in this case, any errors should cause the production line to stop.
if (retval.ErrorOccured) then
ProductionLine.Running = False;
InformationBoard.DisplayText = "ERROR: " + retval.Exception.Message;
InformationBoard.SoundAlarm = True
end if;
的腳本調用WidgetScanned
Python函數:
# pywip/functions.py
from pywip.database import session
from pywip.model import Widget, WidgetHistoryItem
from pywip import validation, StatusMessage
from datetime import datetime
def WidgetScanned(widget_id, scanner_id):
widget = session.query(Widget).get(widget_id)
validation.validate_widget_passed_scanner(widget, scanner) # raises exception on error
widget.history.append(WidgetHistoryItem(timestamp=datetime.now(), action=u"SCANNED", scanner_id=scanner_id))
widget.last_scanner = scanner_id
widget.last_update = datetime.now()
return StatusMessage("OK")
# ... there are a dozen similar functions
我的問題是:如何在這種情況下最好地管理SQLAlchemy會話?應用程序服務器是一個長時間運行的進程,通常在重新啓動之間運行數月。應用程序服務器是單線程的。
目前,我做了以下方法:
我申請一個裝飾,以我做avaliable到應用服務器的功能:
# pywip/iasfunctions.py
from pywip import functions
def ias_session_handling(func):
def _ias_session_handling(*args, **kwargs):
try:
retval = func(*args, **kwargs)
session.commit()
return retval
except:
session.rollback()
raise
return _ias_session_handling
# ... actually I populate this module with decorated versions of all the functions in pywip.functions dynamically
WidgetScanned = ias_session_handling(functions.WidgetScanned)
問:是上述適用於處理會話裝飾在一個漫長的過程中?我應該撥打session.remove()
嗎?
的SQLAlchemy的會話對象是一個範圍的會議:
# pywip/database.py
from sqlalchemy.orm import scoped_session, sessionmaker
session = scoped_session(sessionmaker())
我想保持會話管理出來的基本功能。有兩個原因:
- 還有另一個函數序列函數族。序列函數調用幾個基本函數。一個序列函數應該等於一個數據庫事務。
- 我需要能夠使用來自其他環境的庫。 a)從TurboGears網絡應用程序。在這種情況下,會話管理由TurboGears完成。 b)從IPython shell。在這種情況下,提交/回滾將是明確的。
(對於這個長期的問題我真的很抱歉,但是我覺得我需要解釋一下這個場景,也許沒有必要?)