2016-09-19 9 views
2

Kann jemand erklären, warum Threading nicht in Multiprocessing.Process funktioniert.Python, Threading mit Multiprocessing verwenden

Ich habe ein Beispiel beigefügt, um mein Problem zu erklären.

Ich habe einen Prozess, der jede Sekunde ausgeführt wird und in Datei schreibt. Wenn ich es von der Shell aus starte, funktioniert es wie erwartet.

stat_collect.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

from threading import Timer 
from os import path 
from datetime import datetime 

STAT_DATETIME_FMT = '%Y-%m-%d %H:%M:%S' 


def collect_statistics(): 
    my_file = 'test.file' 
    if not path.exists(my_file): 
     with open(my_file, 'w') as fp: 
      fp.write(datetime.now().strftime(STAT_DATETIME_FMT) + '\n') 
    else: 
     with open(my_file, 'a') as fp: 
      fp.write(datetime.now().strftime(STAT_DATETIME_FMT) + '\n') 

    Timer(1, collect_statistics).start() 


if __name__ == '__main__': 
    collect_statistics() 

Wenn ich versuche, es von anderen Skript ausgeführt werden soll (im Hintergrund arbeiten):

#!/usr/bin/env python 

from multiprocessing import Process 
from stat_collect import collect_statistics # logger sc 

if __name__ == '__main__': 
    # This don't work 
    p = Process(target=collect_statistics) 
    p.start() 

    while True: 
     pass 

Methode collect_statistics nur einmal ausgeführt, aber wenn ich Faden verwenden (target = collect_statistics) .start() funktioniert so, als ob ich es aus der Shell heraus ausführen würde. Warum ist das passiert?

Antwort

1

ist hier was los ist:

  1. Sie Ihren Prozess
  2. collect_statistics Läufe starten
  3. Timer
  4. jetzt gestartet wird, die Funktion im Prozess aufgerufen (collect_statistics) beendet ist, so dass die Prozess beenden, tötet den Timer in der gleichen Zeit.

Hier ist, wie es zu beheben:

stat_collect.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

from threading import Timer 
from os import path 
from datetime import datetime 
import time 

STAT_DATETIME_FMT = '%Y-%m-%d %H:%M:%S' 


def collect_statistics(): 
    while True: 
     my_file = 'test.file' 
     if not path.exists(my_file): 
      with open(my_file, 'w') as fp: 
       fp.write(datetime.now().strftime(STAT_DATETIME_FMT) + '\n') 
     else: 
      with open(my_file, 'a') as fp: 
       fp.write(datetime.now().strftime(STAT_DATETIME_FMT) + '\n') 

     time.sleep(1) 


if __name__ == '__main__': 
    collect_statistics() 

Und für das aufrufende Skript:

#!/usr/bin/env python 

from multiprocessing import Process 
from stat_collect import collect_statistics # logger sc 

if __name__ == '__main__': 
    # This don't work 
    p = Process(target=collect_statistics) 
    p.start() 
    p.join() # wait until process is over, e.g forever 

p.join() ist hier nur zu ersetzen, die Sie unendlich While-Schleife, die für nichts viel Ressource braucht.

+0

Also Aufruf Prozess ist nicht das gleiche wie stat_collect.py von der Befehlszeile ausführen? Und warum tickt Timer, wenn es von Process ausgeführt wird und nicht beendet wird, wenn Skript über die Befehlszeile ausgeführt wird? – Ilya

+0

Sie sollten in Pythons [GIL] (http://www.dabeaz.com/python/UnderstandingGIL.pdf) schauen. Grundsätzlich kommunizieren in Python 2 Prozesse überhaupt nicht miteinander. Das Ausführen von der Befehlszeile aus führt Ihren Code in einem einzigen Prozess aus, und alle Variablen (ein "Timer") werden "gemeinsam genutzt". Das Ausführen in einem anderen Prozess erstellt einen übergeordneten Prozess (das aufrufende Skript) und einen untergeordneten Prozess (erstellt mit 'p = Process (...)'). Der Elternprozess kommuniziert nicht mit dem Kind und hat keine Ahnung, dass ein anderer Thread gestartet wurde. – CoMartel