Dienstag, Februar 18, 2020

Viele threads zu schreiben, log-Datei zur gleichen Zeit in Python

Ich Schreibe ein Skript zum abrufen von WMI-Informationen aus vielen Computern gleichzeitig, dann schreiben Sie diese Informationen in einer text-Datei:

f = open("results.txt", 'w+') ## to clean the results file before the start


def filesize(asset):  
    f = open("results.txt", 'a+')  
    c = wmi.WMI(asset)  
    wql = 'SELECT FileSize,Name FROM CIM_DataFile where (Drive="D:" OR Drive="E:") and Caption like "%file%"'  
    for item in c.query(wql):  
        print >> f, item.Name.split("\\")[2].strip().upper(), str(item.FileSize)  




class myThread (threading.Thread):  
    def __init__(self,name):  
        threading.Thread.__init__(self)  
        self.name = name  
    def run(self):  
        pythoncom.CoInitialize ()  
        print "Starting " + self.name       
        filesize(self.name)  
        print "Exiting " + self.name  



thread1 = myThread('10.24.2.31')  
thread2 = myThread('10.24.2.32')  
thread3 = myThread('10.24.2.33')  
thread4 = myThread('10.24.2.34')  
thread1.start()  
thread2.start()  
thread3.start()  
thread4.start()

Das problem ist, dass alle threads gleichzeitig schreibend.

InformationsquelleAutor user3515946 | 2014-10-12

3 Kommentare

  1. 23

    Können Sie einfach erstellen Sie Ihre eigenen locking-Mechanismus, um sicherzustellen, dass nur ein thread je eine Datei schreiben.

    import threading
    lock = threading.Lock()
    
    def write_to_file(f, text, file_size):
        lock.acquire() # thread blocks at this line until it can obtain lock
    
        # in this section, only one thread can be present at a time.
        print >> f, text, file_size
    
        lock.release()
    
    def filesize(asset):  
        f = open("results.txt", 'a+')  
        c = wmi.WMI(asset)  
        wql = 'SELECT FileSize,Name FROM CIM_DataFile where (Drive="D:" OR Drive="E:") and Caption like "%file%"'  
        for item in c.query(wql):  
            write_to_file(f, item.Name.split("\\")[2].strip().upper(), str(item.FileSize))

    Möchten Sie vielleicht zu prüfen, die Platzierung der Sperre um die gesamte for-Schleife for item in c.query(wql): zu erlauben, jeden thread zu tun, ein größeres Stück Arbeit, bevor die Freigabe der Sperre.

    • Wenn ein thread versucht, write_to_file, während die Datei gesperrt ist, zu einem anderen thread, werden die beiden bekommen noch Ihren Zug zu schreiben?
    • Ja, wenn der thread, der die Sperre freigegeben wird, wird der wartende thread um die Sperre.
    • Ich bin mit diesem Erwerb und die release-Methode für ein python-Skript, wo 4 threads schreiben, um eine Datei gleichzeitig. Es ordentlich richtet die Aufgaben und verhindert Schreibfehler. Ich arbeite gerade an einem zweiten (komplett separates Skript), das schreiben der gleichen Datei wie die erste. Beim laufen in der gleichen Zeit, macht die Sperre erwerben und Methode implementiert, die in dem ersten script auch verhindern, dass der gleichzeitige Zugriff durch das zweite Skript (wo es nicht implementiert)? I. e Funktioniert diese Methode die Datei sperren für jedes Skript versucht, auf dieses zugreifen? …neugierig, aber die Dokumentation ist unklar.
    • Nein, diese Sperre funktioniert nur für threads, die im selben Skript
  2. 6

    print ist nicht thread-sicher. Verwenden Sie die logging – Moduls (welches):

    import logging
    import threading
    import time
    
    
    FORMAT = '[%(levelname)s] (%(threadName)-10s) %(message)s'
    
    logging.basicConfig(level=logging.DEBUG,
                        format=FORMAT)
    
    file_handler = logging.FileHandler('results.log')
    file_handler.setFormatter(logging.Formatter(FORMAT))
    logging.getLogger().addHandler(file_handler)
    
    
    def worker():
        logging.info('Starting')
        time.sleep(2)
        logging.info('Exiting')
    
    
    t1 = threading.Thread(target=worker)
    t2 = threading.Thread(target=worker)
    
    t1.start()
    t2.start()

    Ausgang (und Inhalt results.log):

    [INFO] (Thread-1  ) Starting
    [INFO] (Thread-2  ) Starting
    [INFO] (Thread-1  ) Exiting
    [INFO] (Thread-2  ) Exiting

    Statt den Standardnamen zu verwenden (Thread-n), können Sie Ihre eigenen Namen mit der name Schlüsselwort-argument, das die %(threadName) Formatierung Richtlinie dann nutzen dann:

    t = threading.Thread(name="My worker thread", target=worker)

    (In diesem Beispiel wurde angepasst von einem Beispiel aus Doug Hellmann ‚ s ausgezeichneten Artikel über die threading – Modul)

  3. 3

    Andere Lösung, verwenden Sie ein Pool berechnen von Daten, die Rückgabe an den übergeordneten Prozess. Dieser Elternteil dann schreibt alle Daten in eine Datei. Da gibt es nur ein proc schreiben, die Datei in einer Zeit, gibt es keine Notwendigkeit für eine zusätzliche Sicherung.

    Beachten Sie die folgenden verwendet einen pool von Prozesse, nicht threads. Dies macht den code viel einfacher und leichter, als wenn man etwas zusammen mit der threading Modul. (Es ist ein ThreadPool Objekt, es wird aber nicht dokumentiert.)

    Quelle

    import glob, os, time
    from multiprocessing import Pool
    
    def filesize(path):
        time.sleep(0.1)
        return (path, os.path.getsize(path))
    
    paths = glob.glob('*.py')
    pool = Pool()                   # default: proc per CPU
    
    with open("results.txt", 'w+') as dataf:
        for (apath, asize) in pool.imap_unordered(
                filesize, paths,
        ):
            print >>dataf, apath,asize

    Ausgang results.txt

    zwrap.py 122
    usercustomize.py 38
    tpending.py 2345
    msimple4.py 385
    parse2.py 499

Kostenlose Online-Tests