2009-09-15 5 views
4

Linux에서 Django를 실행 중이며 뷰가 있고 그 뷰가 이라는 서브 프로세스의 데이터를 반환하도록하려는 경우 likeso 예를 들어, 뷰가 생성하는 파일에서 작동 cmd를 : 이제Django에서 시작 시간이 느린 서브 프로세스를 호출하는 방법

def call_subprocess(request): 
    response = HttpResponse() 

    with tempfile.NamedTemporaryFile("W") as f: 
     f.write(request.GET['data']) # i.e. some data 

    # cmd operates on fname and returns output 
    p = subprocess.Popen(["cmd", f.name], 
        stdout=subprocess.PIPE, 
        stderr=subprocess.PIPE) 

    out, err = p.communicate() 

    response.write(p.out) # would be text/plain... 
    return response 

, cmd를가 매우 느린 시작 시간이 생각하지만, 매우 빠른 작동 시간, 그리고 기본적으로 데몬 모드가 없습니다. 이 견해의 응답 시간을 향상시키고 싶습니다.

내가 그들을 입력 대기가 있고, 하나 물어 call_process을 가지고, 전체 시스템이 훨씬 빠르게 노동자 - 풀 cmd를의 인스턴스의 수를 시작하여 실행하는 것하고 싶습니다 작업자 풀 프로세스 중 하나가 데이터를 처리합니다.

cmd를 및 입력 cmd를 대기를 호출 1. 기능 :

이 정말이 개 부분이다. 이는 파이프 (예 :

)
def _run_subcmd(): 
    p = subprocess.Popen(["cmd", fname], 
     stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

    out, err = p.communicate() 
    # write 'out' to a tmp file 
    o = open("out.txt", "W") 
    o.write(out) 
    o.close() 
    p.close() 
    exit() 

def _run_cmd(data): 
    f = tempfile.NamedTemporaryFile("W") 
    pipe = os.mkfifo(f.name) 

    if os.fork() == 0: 
     _run_subcmd(fname) 
    else: 
     f.write(data) 

    r = open("out.txt", "r") 
    out = r.read() 
    # read 'out' from a tmp file 
    return out 

def call_process(request): 
    response = HttpResponse() 

    out = _run_cmd(request.GET['data']) 

    response.write(out) # would be text/plain... 
    return response 

2 부로 수행 할 수 있습니다. 데이터를 기다리는 백그라운드에서 실행중인 근로자 세트. 즉, 하위 프로세스가 이미 실행되도록 위의 내용을 확장하려고합니다.

def init_workers(): # create WORKERS_COUNT workers 
    for i in xrange(0, WORKERS_COUNT): 
     tmp_file = tempfile.NamedTemporaryFile() 
     WORKERS.push(Worker(i)) 

: 장고 인스턴스가 초기화, 또는이 call_process가 처음 호출 될 때, 이러한 노동자의 집합이 같은 곳 근로자의 일부 초기화,이 있어야한다

WORKER_COUNT = 6 
WORKERS = [] 

class Worker(object): 
    def __init__(index): 
     self.tmp_file = tempfile.NamedTemporaryFile("W") # get a tmp file name 
     os.mkfifo(self.tmp_file.name) 
     self.p = subprocess.Popen(["cmd", self.tmp_file], 
      stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
     self.index = index 

    def run(out_filename, data): 
     WORKERS[self.index] = Null # qua-mutex?? 
     self.tmp_file.write(data) 
     if (os.fork() == 0): # does the child have access to self.p?? 
      out, err = self.p.communicate() 
      o = open(out_filename, "w") 
      o.write(out) 
      exit() 

     self.p.close() 
     self.o.close() 
     self.tmp_file.close() 
     WORKERS[self.index] = Worker(index) # replace this one 
     return out_file 

    @classmethod 
    def get_worker() # get the next worker 
    # ... static, incrementing index 

만들어집니다 자, 내가 위에있는 것은 likeso가된다 :

지금 , 질문 :

  1. 이 방법이 유용할까요? (필자는 StackOverflow에 머리 꼭대기에서 이것을 입력 했으므로 문제는 있지만 개념적으로는 효과가 있음을 확신합니다)

  2. 무엇이 문제인가요?

  3. 더 나은 대안이 있습니까? 예 : 쓰레드가 잘 작동 할 수 있습니까? (데비안 레니 리눅스입니까?) 이와 같이 병렬 프로세스 작업자 - 풀을 처리하는 라이브러리가 있습니까?

  4. 내가 장만해야 할 장고와의 상호 작용이 있습니까?

감사합니다! 나는 이것이 내가하는 것처럼 흥미로운 문제로 생각하기를 바랍니다.

브라이언

답변

3

나는 이것이이 권고안에 응답 한 두 번째 시간이므로이 제품을 심심찮게 생각하는 것 같습니다.

그러나 메시지 대기열 서비스, 특히 분산 메시지 대기열이 필요합니다.

  1. 장고 앱이 CMD는
  2. CMD 그것은 실행되고 결과는 상류 반환
  3. 여러 작품에 푸시됩니다 큐에 추가됩니다
  4. CMD
  5. 요청합니다

    오히려 그것이 작동하는 방법이다

이 코드의 대부분이 존재하므로 사용자 시스템을 구축하지 않아도됩니다.

Django로 초기에 만들어진 셀러리를 살펴보십시오. http://robertpogorzelski.com/blog/2009/09/10/rabbitmq-celery-and-django/

+0

이것은 흥미 롭습니다 - 나는 그것에 대해 조사 할 것입니다. 그러나, 내가 가질 수도 있고 가지지 않을 수도있는 문제는 # 4 ("실행 중", 즉 LaTeX가 시작됨)의 파트 1이 # 2 ("CMD가 큐에 추가 됨", 즉 LaTeX가 데이터를 가져 오기 전에)). 그러나 샐러리가이 일을 할 수 있다고 확신합니다. 그러나 약간의 파고가 필요합니다. 고맙습니다 Asksol. –

0

방법 "daemonizing"python-daemon 또는 그 후계자 grizzled를 사용하여 서브 프로세스 호출에 대해.

+0

관련없는 내용이지만 더 나은 것은 무엇입니까? 파이썬 데몬과 관련된 몇 가지 문제가 있었지만 본질적으로 컬렉션 라이브러리에 회의적입니다. – asksol

3

http://www.celeryq.org/

는 이씨는 이미 셀러리를 언급하지만, 의견부터 잘 코드 샘플, 내가 대신 대답으로 답변 해 드리겠습니다 작동하지 않습니다.

셀러리를 AMQP 결과 저장소와 동 기적으로 사용해보십시오. 실제 실행을 다른 프로세스 또는 다른 시스템에 배포 할 수 있습니다. 셀러리에 동 기적으로 실행하면 예를 들어, 쉽게 :

>>> from celery.task import Task 
>>> from celery.registry import tasks 

>>> class MyTask(Task): 
... 
...  def run(self, x, y): 
...   return x * y 
>>> tasks.register(MyTask) 

>>> async_result = MyTask.delay(2, 2) 
>>> retval = async_result.get() # Now synchronous 
>>> retval 4 

AMQP 결과 저장소가 매우 빠르고, 을 결과를 다시 보낼 수 있지만 ( 0.8.0가 될 코드 동결) 현재 개발 버전에서만 사용할 수

+0

하나의 요구 사항은 작업을 영원히 데몬으로 실행 한 다음 데몬에서 데이터를 보내거나받는 것입니다. run()을 호출하기 전에 LaTeX가 실행 중이어야합니다 (그렇지 않으면 LaTeX이 시작될 때까지 기다려야하므로 태스크 대기열 사용의 전체 목적을 피할 수 있습니다). 나는 그것이 할 수 있는지보기 위해 셀러리를 조사하고있다. –

+0

최적화와 달리 LaTeX가 실행되어야한다는 요구 사항이 표시되지 않습니까? 이렇게하려면 LaTeX C API (또는 무엇이든)를 사용하여 작업자 프로세스 내부에 임베드를 실행해야합니다. 이것은 가능해야하지만 셀러리를 상당히 사용자 정의해야합니다. 이미 문제의 일부를 해결하기 때문에 좋은 출발점 일 수 있습니다. 나는 작업 대기열이 이것에 잘 들어 맞았다 고 말하지는 않았지만 분산/병렬 처리 부분은 *있을 수도있다. 태스크 풀을 원하고 결과를 보내고 받기를 원하면 작업자 프로세스가 LaTeX 프로세서가되기를 바랄뿐입니다. – asksol

관련 문제