2017-12-13 9 views
0

장고 (Django), 플라스크 (Flask), 셀러리 (Celery) 등 여러 데몬을 사용하는 애플리케이션이 있습니다.파이썬에서 인수로 직접 전달하지 않고도 잠금 또는 세마포를 만들 수 있습니까?

우리는 클라이언트 측에서 요청을 받고 샐러리를 사용하여 비동기 적으로 요청을 실행하기 위해 장고 휴식 프레임 워크를 사용하고 있습니다. 이는 여러 개의 동시 파이썬 프로세스가 실행 중일 수 있음을 의미하지만 다중 처리 또는 기타 원시 파이썬 동시 처리를 사용하지는 않습니다.

그럼에도 불구하고 다른 프로세스간에 공유 잠금을 갖고 싶습니다. 이런 종류의 유스 케이스에서 파이썬의 잠금 또는 세마포어를 사용할 수있는 방법이 있습니까?

또는 셀러리를 사용하여 처리 할 수 ​​있습니까?

편집 : @Matias 키케로에 의해 제안은, 파일 잠금을 사용하기에 충분

내 사용 사례를 들어.

그러나 잠금을 사용하여 문제를 해결하고 여러 개의 추가 공유 리소스를 제공하는 관리자를 사용하도록 제안 했으므로 허용 된대로 @Aaron 응답을 선택했습니다. 이것은 사실 내 요구에 매우 유용한 솔루션입니다.

감사합니다.

+0

나에게 보인다 당신은 프로세스들 사이에 공유 잠금을 원한다. * [파일 잠금] (https://en.wikipedia.org/wiki/File_locking) *을 사용하는 것은 어떨까요? –

+0

당신은 [''multiprocessing.Manager'] (https://docs.python.org/3.6/library/multiprocessing.html#using-a-remote-manager)를'mp.BaseManager '를 가진 ip/port로 지정할 수 있습니다. get_server()'. 이 mamager는 기존 프로세스 중 하나에서 호스팅되거나 다른 프로세스에서 서비스 할 수 있습니다 (어느 것이 먼저 시작되거나 다른 프로세스보다 먼저 실행될 수 있음) – Aaron

+0

내 프로세스가 동일한 시스템에서 실행되므로 생각합니다. ip와 port는 나에게 좋은 방법이 아닐 수도 있습니다. 파일 잠금은 내 용도로 좋은 생각입니다. 파이썬의 파일 잠금 패키지를 사용하는 것이 좋습니다? – orizis

답변

1

마지막 코멘트에 설명 된 내용은 기본적으로 정확히 무엇을 할 것인가입니다. 동기화 관리자 서버를 시작하기 전에 잠금을 작성하고 해당 잠금을 리턴 할 서버 오브젝트에 함수를 등록하십시오. 그런 다음 다른 프로세스에서 서버에 연결할 때 해당 등록 된 함수를 호출하여 잠금 객체를 반환합니다 (실제로 잠금에 대한 프록시 객체이지만 동일한 기능을 수행해야 함). 이것은 변경 가능한 컨테이너 (dicts, lists, 등). 프록시 내의 값을 수정해도 프록시 자체가 업데이트되지 않을 수 있습니다.

다음은 잠금을 보유하고 프록시 객체를 요청하는 클라이언트에 프록시 객체를 전달하는 간단한 서버의 예입니다.

server.py :

"""Multiprocessing sync manager server process""" 
from multiprocessing import Lock 
from multiprocessing.managers import BaseManager 

class proxy_object_manager(BaseManager): pass 
plock = Lock() 
proxy_object_manager.register("get_lock", callable=lambda:plock) 

#make sure this port is firewalled off from the rest of the world. 
# arbitrary code execution is a very real possibility if this is insecure. 
# be sure to read up on how this all works if you intend to expose this computer to the internet 
m = proxy_object_manager(('',50000), b'password') 
m.get_server().serve_forever() 

client.py (오픈 두 개별 단자 이들보다, 그 후 하나의 입력 키를 눌러 (그 자체가 단자 창의이 먼저 시작) 당신은 당신이 처음에 손을 뗄 때까지 그러나 두 번째 인스턴스가 잠금을 획득하지 말아야 client.py의 첫 번째 인스턴스가 바로 잠금을 획득 볼 수

""" multiprocessing sync client example """ 
from multiprocessing.managers import BaseManager 

# I played around a bit with making more functional subclasses 
class proxy_object_client(BaseManager): 
    def __init__(self, proxy_getter, *args, **kwargs): 
     type(self).register(proxy_getter) 
     super().__init__(*args, **kwargs) 

client = proxy_object_client("get_lock", ("127.0.0.1", 50000), b"password") 
client.connect() 
plock = client.get_lock() 
print(plock) 

#test lock functionality 
print("aquiring lock") 
plock.acquire() 
print("got lock") 
input("press enter to release lock") 
plock.release() 
print("lock released") 

) 기타 예.

둘점 : 우리 client.py에서

  • 는, PLOCK는 명시 적으로 노출되거나 수 있어야합니다 (컨텍스트 "로"처리와 같은 __enter____exit__)이이 프록시를 개체의 공개 방법, 그래서 개인 메서드를 공개한다 BaseProxy 하위 클래스로 프록시 유형을 지정하여 사용할 수 있습니다.
  • "with"컨텍스트를 사용하여 파이썬 3부터 서버를 시작할 수 있습니다.3, 그러나 당신은 을 manager.__enter__()과 함께 사용할 때 호출 함수로 람다 함수를 등록 할 수 없습니다.이 함수는 "with"를 사용할 때 발생합니다 (이것은 윈도우에서만 가능).
  • manager.start() 또는 "with"컨텍스트를 사용하여 주 모듈을 다시로드하는 프로세스를 시작하면 server.py에서 if __name__ == "__main__":이라는 관용구를 사용하여 서버를 시작하는 것이 필수적입니다. 따라서 포크 폭탄이 효과적으로 발생합니다 . 다행히 멀티 프로세싱 모듈은 이것을 인식 할만큼 똑똑하고 그렇게하지 않을 것이지만,이 경우 다중 처리 모듈은 단지 예외를 던집니다. (multiprocessing를 사용하는 경우 일반적으로, if __name__ ... 조건의 외부의 서브 프로세스를 생성하지 않습니다.) 여기

는 (다소) 주소 "server.py"이러한 우려의 예 :

from multiprocessing import Lock, freeze_support 
from multiprocessing.managers import BaseManager 


class proxy_object_manager(BaseManager): pass 
plock = Lock() 
def lock_getter(): 
    return plock 
proxy_object_manager.register("get_lock", callable=lock_getter, exposed=['acquire', 'release', '__enter__', '__exit__']) 

if __name__ == "__main__": 
    freeze_support() #needed on windows 
    with proxy_object_manager(('127.0.0.1',50000), b'password'): 
     input("press enter to stop server") 
+0

고마워요! 정말 도움이되었고이 예를 들어 주신 노력에 감사드립니다. 제대로 이해하면 각 공유 리소스를 사용하고자하는 횟수만큼 등록해야합니다. 코드에서 일부 중복됩니다. 한번 호출 가능하도록 등록한 다음 관리자 클래스의 일부로 다른 시간을 등록하여 재사용 할 수 있습니까? 여러 구성을 피하기 위해 관리자를 다시 사용할 수 있습니까? – orizis

+0

@orizis 한 관리자는 여러 가지 일을 등록 할 수 있지만, 여전히 유동적 인 인터페이스는 아닙니다. 나는 이것이 어떻게 더 아름답게 만들어 질 수 있는지 더 많은 것을보고있다.하지만 나는 그 장면 뒤에 무엇이 있더라도 추악 할 것이라고 생각한다. – Aaron

+0

@orizis 더 자세히 살펴보면 관리자는 대부분 자식 프로세스와 공유하도록 만들어 졌음을 알 수 있습니다. 서버 옵션은 값 싸게 추가 될 수 있다는 것을 깨달았지만 프레임 워크는이를 염두에두고 설계되지 않았습니다. – Aaron