2010-11-28 8 views
0

Ich habe folgende Python-Code in Datei, die Daten aus dem seriellen Port kommenden erwartet, und schreibt sie in eine Datei.Mehrere schreibt

import time 
import serial 

def write_log (text): 
    f = open('logger.log', 'a') 
    f.write(text) 
    f.close() 

ser = serial.Serial() 
ser.port = "/dev/ttyS0" 
ser.baudrate = 4800 
ser.open() 
if ser.isOpen(): 
    while 1: 
     while ser.inWaiting() <= 0: 
      time.sleep(1) 
      response = ser.read(ser.inWaiting()) 
      if len (response): 
       write_log(response) 
       print response 

Es in einem Ausmaß, wie es nach einiger Zeit arbeitet, beginnt es zu hängen, bis die CPU den ganzen Weg zu bringen, und nichts zu schreiben (oder manchmal nur Textstücke zu schreiben) in die Logdatei.

Der Prozess hier ist ziemlich intensiv, da meine serielle Schnittstelle eine 8-Byte-Zeichenfolge jede Sekunde schreiben wird, und dieses Python-Skript soll es dann empfangen und seinen Inhalt in die Protokolldatei schreiben.

ich das Problem hier denke, ist die Tatsache, dass ich das Öffnen und Schließen der Datei zu viel, und das irgendwie macht den gesamten Prozess langsam. Ich bin kein Python-Wizz, daher würde jede Hilfe oder jeder Ratschlag zur Verbesserung dieses Codes sehr geschätzt werden.

Vielen Dank im Voraus,

+0

8 Byte pro Sekunde nicht sehr intensiv ist; 8 MiB/s mögen intensiv sein, aber die meisten CPUs können damit zurechtkommen. Selbst ein Z80, der mit 4 MHz läuft, würde 8 Bytes pro Sekunde nicht intensiv finden. –

+0

Ich weiß, dass es nicht sehr intensiv ist, aber irgendwie reagiert dieser Code nach einiger Zeit nicht mehr und speichert nichts mehr. Ich sage intensiv, weil es versuchen wird, Zeug in serielle zu schreiben, auch wenn das Python-Skript nichts in die Textdatei schreibt –

+0

Der Code sieht aus, vom seriellen Gerät zu lesen, nicht zu schreiben. –

Antwort

0

ich glaube, das Problem ist, dass Sie das Dokument abrufen für Updates.

Python serial.read() Funktionsblocks tatsächlich der aktuelle Thread, bis etwas auf dem Faden lesbar wird, bis zum Timeout. Was Sie also tun sollten, ist einen anderen Thread auszubreiten, um serielle IO zu behandeln. Lassen Sie es endlos loopen, indem Sie eine Bedingung überprüfen (der Master-Thread möchte, dass Sie weiterhören und der serielle Port noch verfügbar ist). Dieser Thread etwas tun wird, wie:

while ser.isOpen() && thisthread_should_keep_doing_this: 
    response = ser.read(ser.inWaiting()) 
    if len(response): 
     write_log(response) 
     print response 

Dann, wenn Sie es verlassen möchten, Ihr Master-Thread setzt thisthread_should_keep_doing_this=False und wenn Ihr Slave-Thread zu Ende gelesen hat, es tötet sich selbst.

Zwei Dinge:

  • Sie relativ häufig die Lese Timeout haben.
  • Nicht "Remote Kill" den Faden. Gib ihm eine Nachricht und lass es sich selbst töten. Töten von Threads aus der Ferne schafft eine schreckliche Unordnung.

Siehe http://pyserial.sourceforge.net/examples.html#miniterm

+0

Nicht sicher, ich verstehe wirklich, was hier zu tun ist. Auch hier bin ich kein Python Wizz und habe noch nie mit Threads gearbeitet. Ihre Idee scheint jedoch eine vernünftige Lösung für mein Problem zu sein. –

+0

@Marcos Die Idee ist ziemlich einfach, aber wirklich schwer, den Kopf herum zu bekommen, wenn das Sinn macht. Blockieren von IO ist im Grunde wie Schlaf. Ihr Thread wird unter zwei Bedingungen aktiviert: Daten werden ausgegeben oder die Verzögerung läuft ab. Was Sie dann tun, ist zu überprüfen, dass der Port offen ist und Sie nicht aussteigen wollen, dann versuchen Sie erneut zu lesen und lassen Sie den gelesenen Block weg. Indem Sie zwei Threads erstellen, können Sie einen für diesen Zweck opfern und einen, um mit dem Hauptgeschäft des Programms weiterzumachen (selbst wenn das nur auf die Anweisung "exit" wartet). –

+0

Bei blockierender E/A-Funktion lesen Sie sofort, wenn viele Daten eingehen. Wenn nicht, schlafen Sie für das Zeitüberschreitungsintervall. Mit DEINER Lösung schläfst du 1 Sekunde und ziehst, was auch immer da ist. Für diese 1 Sekunde könnten Sie also Taktzyklen verwenden, um Daten zu lesen, aber Sie sind es nicht. Dann gibt es viele Daten ... und Sie erhalten unvorhersehbare Ergebnisse. –

1

Sie haben eine unendliche Schleife in Ihrem Code, und Sie brechen aus es nicht, wenn ein Problem gibt es - oder das serielle Gerät ist nicht mehr offen.

Wahrscheinlich verwenden:

while ser.isOpen(): 
    while ser.inWaiting() <= 0: 
     time.sleep(1) 
     response = ser.read(ser.inWaiting()) 
     if len(response): 
      write_log(response) 
      print response 

oder sogar:

while ser.isOpen() && ser.inWaiting() <= 0: 
    time.sleep(1) 
    response = ser.read(ser.inWaiting()) 
    if len(response): 
     write_log(response) 
     print response 

Ich bin über den Schlaf nicht sicher, entweder; Sie würden es besser machen, wenn Sie nur im Lesemodus warten, bis Daten verfügbar sind.

Wenn ich darüber nachdenke, die Methoden in der seriellen Klasse nicht zu kennen, desto mehr denke ich, dass die Hauptschleife versuchen sollte, vom seriellen Gerät zu lesen, glücklich zu hängen, wenn momentan nichts verfügbar ist und nur zu beenden Die Eingabemethode zeigt an, dass keine Eingabe mehr erfolgt - das Gerät wurde bei Ihnen geschlossen oder ist in irgendeiner Weise ausgefallen.

+0

Ihr Beispiel stirbt nach einiger Zeit auch –

+0

@Marcos: OK, aber ohne eine Spezifikation des seriellen Pakets (ist das Standard Python? Ich bezweifle es) wird es sein schwer zu wissen, was Sie tun müssen. Doppelt so, da ich Python nur wirklich lesen kann und es nicht flüssig schreiben kann. Aber Sie sollten darauf zielen, dass die Schleife (singulär - nicht verschachtelt) synchron gelesen wird; Es hängt einfach in der Lese, bis Daten bereit sind. Wenn diese Funktion nicht bereits verfügbar ist, sollten Sie eine Funktion schreiben, um sie bereitzustellen. Wenn Sie wirklich abstimmen müssen, sollten Sie häufiger als einmal pro Sekunde eine Mikro-Schlaffunktion verwenden. –