문제

대본:

  • .NET 기반 애플리케이션 서버 (Wonderware IAS/시스템 플랫폼) 공장 바닥의 다양한 장비와 통신하는 자동화 객체를 호스트합니다.
  • Cpython 은이 응용 프로그램 서버 내에서 호스팅됩니다 (사용 .NET 용 Python).
  • 자동화 객체에는 스크립팅 기능이 내장되어 있습니다 (사용자 정의 .NET 기반 언어 사용). 이 스크립트는 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 파이썬 기능 :

# 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 세션을 가장 잘 관리하는 방법은 무엇입니까? 애플리케이션 서버는 장기적인 프로세스이며 일반적으로 재시작 사이에 몇 개월을 실행합니다. 응용 프로그램 서버는 단일 스레드입니다.

현재 다음과 같은 방법으로 수행합니다.

나는 응용 프로그램 서버에 불가능하게 만드는 기능에 데코레이터를 적용합니다.

# 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())

세션 관리를 기본 기능에서 유지하고 싶습니다. 두 가지 이유로 :

  1. 다른 기능, 시퀀스 기능이 있습니다. 시퀀스 기능은 여러 기본 기능을 호출합니다. 하나의 시퀀스 함수는 하나의 데이터베이스 트랜잭션과 같아야합니다.
  2. 다른 환경에서 도서관을 사용할 수 있어야합니다. a) 터보 가어스 웹 애플리케이션에서. 이 경우 세션 관리는 터보 가어에 의해 수행됩니다. b) Ipython 쉘에서. 이 경우 커밋/롤백이 명시 적입니다.

(긴 질문에 대해 정말 죄송합니다.하지만 시나리오를 설명해야한다고 느꼈습니다. 아마도 필요하지 않습니까?)

도움이 되었습니까?

해결책

설명 된 데코레이터는 장기적인 응용 프로그램에 적합하지만 실수로 요청간에 객체를 공유하면 문제가 발생할 수 있습니다. 오류가 더 일찍 나타나고 손상되지 않도록하려면 세션을 사용하여 세션을 폐기하는 것이 좋습니다. remove ().

try:
    try:
        retval = func(*args, **kwargs)
        session.commit()
        return retval
    except:
        session.rollback()
        raise
finally:
    session.remove()

또는 사용할 수있는 경우 with 컨텍스트 관리자 :

try:
    with session.registry().transaction:
        return func(*args, **kwargs)
finally:
    session.remove()

그건 그렇고, 당신은 사용하고 싶을 수도 있습니다 .with_lockmode('update') 쿼리에서 유효성 검사가 오래된 데이터에서 실행되지 않습니다.

다른 팁

Wonderware 관리자에게 Wonderware Historian에 액세스 할 수 있도록 요청하십시오. SQLALCHEMY를 통해 MSSQL 통화를 통해 태그 값을 매우 쉽게 추적하여 자주 투표 할 수 있습니다.

또 다른 옵션은 Archestra 툴킷을 사용하여 내부 태그 업데이트를 듣고 서버를 Galaxy에서 플랫폼으로 배포하는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top