2013-07-18 26 views
5

Çok fazla arama yaptım ve çıktıyı çalışan bir python alt işleminden Tornado'ya nasıl alıyorum. İstediğim şey Travis CI gibi bir şey. Bir yönetici sayfasında işi başlatacağım, sunucu isteği alacak ve bir alt işlem başlatacaktır. Bu alt işlem bazı veri madenciliği yapacak ve bazı günlükler içeren bir dize arabelleği besleyecektir. Bu günlükleri, aceleyle ya da bir websocket ile ajax ile alacağım ve bu günlükleri sayfaya getireceğim. Kullanıcı sayfayı kapatıp daha sonra geri dönse bile, günlükler olacak ve normalde güncellenecektir. Aslında Travis'e çok benziyor. Esasen sonrası uyumsuz stdout ve stderr hem okuyarak bir sürecin çıkış okurken kilitlenme önlemek için nasıl gösterir http://stefaanlippens.net/python-asynchronous-subprocess-pipe-readingBir python altişlem işinden çıktıyı tornado haline getirin

:

cevap

3

Bu blog yazısı Bunu yapmanın bir yolu gösterir. İstediğiniz komutu çalıştırmak için producer komutunu __main__'dan ve çıktıyı Tornado'da işlemek için kod içeren yazdırma ifadeleriyle değiştirebilirsiniz.

Güncelleme: Ben durumunda günlüğü yayından kaldırıldığında aşağıdakiler dahil ettik: Örneğin standart çıktı ve çizgi ile hata çizgisini okumak istiyorsanız neyi

... izlemek istediğiniz çünkü daha uzun bir çalışma süreci? web sitesinde, farklı derecelerde karmaşıklığı, soyutlama ve bağımlılıkları olan birçok çözüm bulabilirsiniz. Bir çözüm ( kodlu ve standart kütüphanenin dışında bir bağımlılık ile birlikte) borularını ayrı dişlerde okumaktır, böylece bir boru diğerini engelleyemez.

Aşağıdaki kod örnek bir uygulamayı göstermektedir. Komut, 'u, alt öğe için alt öğe olarak kullanılan şekilde ayarlanmıştır.

Alt işlem için: 'üretmek' argümanı ile çağrıldığında, standart çıktıda ve standart hatada bazı satırları rasgele bir şekilde gösteren Produ() işlevini çalıştırır. Çizgiler arasında, numaralı bir dokunuşun gecikmesi, daha uzun bir çalışma sürecini simüle eder. Consume() işlevinde uygulanan ana işlem (argümansız çağrılan komut dosyası), "alt modda" aynı komut dosyasını alt işleminde çağırır ve her satırın hangi borudan geldiğini önceden bilmeden satırın çıkış satırını izler. Hadi.

AsynchronousFileReader sınıfı zaman uyumsuz standart çıktı ve hata boruları okumak ve sıradaki her satırı koyun parçacığı içindir. Ana iş parçacığı, alt işlemlerini, kuyruklarda geldiklerinde satırlarını izleyerek izleyebilir.

import sys 
import subprocess 
import random 
import time 
import threading 
import Queue 

class AsynchronousFileReader(threading.Thread): 
    ''' 
    Helper class to implement asynchronous reading of a file 
    in a separate thread. Pushes read lines on a queue to 
    be consumed in another thread. 
    ''' 

    def __init__(self, fd, queue): 
     assert isinstance(queue, Queue.Queue) 
     assert callable(fd.readline) 
     threading.Thread.__init__(self) 
     self._fd = fd 
     self._queue = queue 

    def run(self): 
     '''The body of the tread: read lines and put them on the queue.''' 
     for line in iter(self._fd.readline, ''): 
      self._queue.put(line) 

    def eof(self): 
     '''Check whether there is no more content to expect.''' 
     return not self.is_alive() and self._queue.empty() 

def consume(command): 
    ''' 
    Example of how to consume standard output and standard error of 
    a subprocess asynchronously without risk on deadlocking. 
    ''' 

    # Launch the command as subprocess. 
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

    # Launch the asynchronous readers of the process' stdout and stderr. 
    stdout_queue = Queue.Queue() 
    stdout_reader = AsynchronousFileReader(process.stdout, stdout_queue) 
    stdout_reader.start() 
    stderr_queue = Queue.Queue() 
    stderr_reader = AsynchronousFileReader(process.stderr, stderr_queue) 
    stderr_reader.start() 

    # Check the queues if we received some output (until there is nothing more to get). 
    while not stdout_reader.eof() or not stderr_reader.eof(): 
     # Show what we received from standard output. 
     while not stdout_queue.empty(): 
      line = stdout_queue.get() 
      print 'Received line on standard output: ' + repr(line) 

     # Show what we received from standard error. 
     while not stderr_queue.empty(): 
      line = stderr_queue.get() 
      print 'Received line on standard error: ' + repr(line) 

     # Sleep a bit before asking the readers again. 
     time.sleep(.1) 

    # Let's be tidy and join the threads we've started. 
    stdout_reader.join() 
    stderr_reader.join() 

    # Close subprocess' file descriptors. 
    process.stdout.close() 
    process.stderr.close() 

def produce(items=10): 
    ''' 
    Dummy function to randomly render a couple of lines 
    on standard output and standard error. 
    ''' 
    for i in range(items): 
     output = random.choice([sys.stdout, sys.stderr]) 
     output.write('Line %d on %s\n' % (i, output)) 
     output.flush() 
     time.sleep(random.uniform(.1, 1)) 

if __name__ == '__main__': 
    # The main flow: 
    # if there is an command line argument 'produce', act as a producer 
    # otherwise be a consumer (which launches a producer as subprocess). 
    if len(sys.argv) == 2 and sys.argv[1] == 'produce': 
     produce(10) 
    else: 
     consume(['python', sys.argv[0], 'produce']) 
+1

sayfa 404 :( –

+1

dönüyor ben daha böyle bir şey durumda blog alıntı ettik. – funkotron