2016-10-12 3 views
2

Python 클래스는 rpy2를 통해 R 함수를 실행하며 R 함수가 오류를 생성하는 경우 R에서 추적을 캡처 할 수 있기를 원합니다.RRuntimeError가 발생했을 때 R에서 추적 추적 캡처

R 코드는 레거시이므로 수정하는 것은 매우 위험 할 수 있습니다. 나는 파이썬 측면에서 뭔가를하는 것을 선호한다.

from rpy2.rinterface import RRuntimeError 
from rpy2.robjects import DataFrame 
from rpy2.robjects.packages import InstalledPackage 

class RAdapter(BaseRAdapter): 
    _module = None # type: InstalledPackage 

    def call_raw(self, function_name, *args, **kwargs): 
     # type: (str, tuple, dict) -> DataFrame 
     """ 
     Invokes an R function and returns the result as a DataFrame. 
     """ 
     try: 
      return getattr(self._module, function_name)(*args, **kwargs) 
     except RRuntimeError as e: 
      # :todo: Capture traceback from R and attach to `e`. 
      e.context = {'r_traceback': '???'} 
      raise 

    ... 

어떻게 그렇게는 R 기능이 오류가 발생하는 경우에 R의 역 추적을 캡처하는 call_raw을 수정해야합니다 :

다음은 파이썬 코드가 현재의 모습입니까?

답변

2

traceback()rpy2.robjects.r을 사용하여 traceback() 함수를 평가하고 그 결과를 직접 Python 변수에 저장할 수 있습니다.

rpy2 v2.8.x에 대한 참고 사항 : traceback()의 결과는 rpy2 can work with just fine 인 pairlist이지만 an issue that prevents repr from working correctly입니다. 코드를 디버그하기 쉽도록하려면 unlist을 사용하여 쌍 목록을 목록으로 변환하십시오.

traceback()도 추적 출력을 stdout으로 보내고 [임시적으로] sys.stdout을 제외하고는이를 피할 수있는 방법이 없다는 것을 알고 있어야합니다.

from rpy2.rinterface import RRuntimeError 
from rpy2.robjects import DataFrame 
from rpy2.robjects.packages import InstalledPackage 

class RAdapter(BaseRAdapter): 
    _module = None # type: InstalledPackage 

    def call_raw(self, function_name, *args, **kwargs): 
     # type: (str, tuple, dict) -> DataFrame 
     """ 
     Invokes an R function and returns the result as a DataFrame. 
     """ 
     try: 
      return getattr(self._module, function_name)(*args, **kwargs) 
     except RRuntimeError as e: 
      # Attempt to capture the traceback from R. 
      # noinspection SpellCheckingInspection 
      try: 
       # noinspection SpellCheckingInspection 
       e.context = { 
        # :kludge: Have to use `unlist` because `traceback` 
        # returns a pairlist, which rpy2 doesn't know how 
        # to handle. 
        'r_traceback': '\n'.join(r('unlist(traceback())')) 
       } 
      except Exception as traceback_exc: 
       e.context = { 
        'r_traceback': 
         '(an error occurred while getting traceback from R)', 

        'r_traceback_err': traceback_exc, 
       } 

      raise 

    ... 

rpy2==2.8.3로 테스트 :

여기 RAdapter.call_raw()가 R의 역 추적을 캡처 할 수있는 방법입니다.

1

rpy2은 R 페어리스트를 (대부분) 잘 처리 할 수 ​​있습니다. 그러나 그들의 표현 (방법 __repr__)에는 버그가있는 것으로 보입니다. R 벡터의 경우 일반 __repr__은 조각을 사용하고 조각 목록 개체는 조각을 사용할 수 없습니다.

>>> from rpy2.robjects import baseenv 
>>> opts = baseenv['.Options'] 
>>> opts.typeof # this is a pairlist 
2 
>>> print(opts) # working 
... 
>>> str(opts) # working 
>>> opts.items() # working 
>>> repr(opts) # ValueError: Cannot handle R type 2 
+0

설명해 주셔서 감사합니다! 후속 조치를 위해 [rpy2 repo에 관한 문제] (https://bitbucket.org/rpy2/rpy2/issues/380/valueerror-when-getting-repr-of-a-pairlist)를 기록했습니다. – user5568265