2009-08-26 3 views
1

MySQLDb는 약한 프록시를 사용하여 커서와 연결 간의 순환 종속성을 방지합니다.weakproxy가 파이썬에서 항상 동등성을 유지하지 않는 이유는 무엇입니까?

그러나 weakref에 대한 설명서에서 동등성을 테스트 할 수 있다고 기대할 수 있습니다. 아직 :

In [36]: interactive.cursor.connection.thread_id() 
Out[36]: 4267758 

In [37]: interactive.web_logic.conns.primary.thread_id() 
Out[37]: 4267758 

In [38]: interactive.cursor.connection == interactive.web_logic.conns.primary 
Out[38]: False 

In [39]: interactive.cursor.connection 
Out[39]: <weakproxy at 0x3881c60 to Connection at 0x94c010> 

In [40]: interactive.web_logic.conns.primary 
Out[40]: <_mysql.connection open to 'xendb01' at 94c010> 

연결이 동일한 지 어떻게 알 수 있습니까?

답변

0

개체가 표준 weakref 인 경우 개체를 가져 오려면 해당 개체를 호출해야합니다. 여기 weakrefs를 사용

import weakref 
class Test(object): pass 
a = Test() 
b = weakref.ref(a) 
a is b() # True 
a == b() # True 

하지만, 잘못된 것 같다 내가 연결을 구성하는 경우, 커서가 유효해야 그것에서 커서를 작성하고 연결 개체를 폐기합니다. 연결에서 모든 커서의 목록을 유지하지 않는 한 순환 종속성이 없어야합니다.이 경우 이고 weakref가되어야합니다.

+0

weakproxy가 아니라 약점입니다. weakproxy 구현의 약점은 무엇입니까? – rhettg

+0

아, weakref.proxy를 의미합니다 ("weakproxy"가 아님, 적어도 Python 표준 lib에는 없 음). 원본 개체를 검색하는 방법은 노출되지 않는 것으로 보입니다. 이는 형식의 주요 제한 사항처럼 보입니다. 그것은 감독되어야합니다. 이 제한은 완전히 불필요한 것처럼 보입니다. 객체가 프록시인지 (obj .__ str __()을 파싱하려고 시도하는 것보다 짧은 지) 확인할 수있는 방법조차 없다. 이 유형은 완전히 겉으로 드러난 것처럼 보이지 않습니다. –

+0

그렇다면 "obj1 .__ dict__은 obj2 .__ dict__"입니다. ("30 초마다 하나의 주석 만 게시 할 수 있습니다."이 사이트는 때때로 자극적입니다.) –

3

나는 오랫동안 weakref.proxy의 디자인과 구현이 다소 불안정한 것으로 나타났습니다. 목격자 :

>>> import weakref 
>>> ob=set(range(23)) 
>>> rob=weakref.proxy(ob) 
>>> rob==ob 
False 
>>> rob.__eq__(ob) 
True 

... DEFINITELY 특유의! 실제로 내가 weakref에서 사용하는 것은 약점이거나 때때로 약한 사전입니다. 하지만 weakref.ref는 그 위에 프록시 래퍼보다는 측심기는 다음과 같습니다

>>> wr=weakref.ref(ob) 
>>> wr()==ob 
True 

그래서 (불행하게도이 불투명하게 (개체가 사라진 이후이있는 경우 또는 없음) 심판 개체를 얻을하는 "전화"의 필요성 DB API 모듈은 API 준수 상태를 유지할 수 없습니다). 나는 왜 MySqlDb가 약한 커서 -> 연결 참조를 원하는지 이해하지 못한다. 그러나 그들이 그렇게한다면 그들이 왜 그들이 refs가 아닌 proxy를 사용해야 만 하는지를 알게된다. 그러나, 그 투명성에 대해 매우 높은 가격을 지불합니다!

Btw, "명백한 __eq__"트릭 (또는 기본 객체의 유형에 따라 __cmp__에 해당하는 동등한 트릭)이 도움이 될 수 있습니다.

+0

필자는 항상 프락시가 ref와 같은 함수를 호출하지 않아도되는 매우 추한 추상화 매직 마술을 끌어 올린다고 생각했다. 지금 나는 확실히 알고있다. – Unknown

+0

당신의 "특별한"비교 결과는 set .__ eq__가 프록시에 대해 알지 못하기 때문입니다. 다른 객체가 세트가 아니므로 False를 반환합니다.rob .__ eq__는 ob .__ eq__에서 프락시되기 때문에 그 방향으로 작동합니다. 좋은 해결책이없는 사마귀입니다. (옵션은 설정하고 다른 모든 유형은 weakref.proxy의 인스턴스를 검사하거나 __eq__ 등을 호출하기 전에 파이썬 인터프리터를 투명하게 대체해야합니다.) –

+0

@Matthew :별로는'rob == ob' 및'ob == rob'은 모두 false입니다 (그러나'rob .__ eq __ (ob)'과'ob .__ eq __ (rob)'는 당신이 지시하는대로 행동합니다). 충분하게 투명한 프록시를 만들 수있는 좋은 방법이 없을 수도 있습니다. 우리가 처음에 시도한 것은 불행합니다. -) –

1

랩 비 weakref.proxy와 프록시와 정체성 연산자 사용

>>> interactive.cursor.connection is weakref.proxy(interactive.web_logic.conns.primary) 
True 

호출 weakref.proxy은() 두 번 같은 프록시 개체를 반환합니다.

+0

그건 일종의 추한 것입니다. 양쪽이 프록시라고 가정하고 싶지 않은 경우 양측에서도해야합니다. obj .__ dict__가 다른 객체 (예 : 여러 객체가 __dict__를 공유)에 할당되는 일부 모호한 경우에는 작동하지만 대부분의 경우 나는 여전히 __dict__을 비교하는 것에 집중할 것이라고 생각합니다. –

+0

실제로는 꽤 멋진 해킹입니다. 추측하기 전에 비교하기 전에 모든 피연산자를 weakref.proxy로 변환 할 수 있습니다. weakref.proxy를 전체 응용 프로그램을 감염시키는 바이러스로 만듭니다 ...... – rhettg

+0

또한이 동작이 보장된다고 가정합니다. 문서에 언급 된 동작을 보지 못하기 때문에 의존하지 말아야하는 최적화 느낌이 있습니다. 그것은 아마 합리적으로 안전 할 것이지만, 코드에서 이것을 많이 사용하게되고 나중에 가정이 깨지면 문제를 해결하기 어려워 질 수 있습니다. –

관련 문제