Mir ist nicht ganz klar, was du als Ergebnis deines Programms erwartest. Du schreibst, es soll "ab einer bestimmten Größe eine Funktion ausgeführt werden". Vermutlich statt des
print "Filesize > 5kb". So, wie du es programmiert hast, funktionierst du deinen Rechner zur Heizung um und vergeudest massiv Rechenzeit. Solange die Dateigröße < 5000 ist, können beliebig viele Schleifendurchläufe in Thread2 stattfinden, je nachdem, wie lange das Lesen von COM1 und das Schreiben in log.txt in Thread1 jedesmal dauert. Aber selbst wenn die Dateigröße >= 5000 kB ist, wird geloopt werden, was der Prozessor hergibt, nur dass dann bei jedem Durchlauf deine Funktion wieder und wieder gestartet wird, solange, bis entweder die Abbruchbedingung erfüllt ist, oder die Datei wieder kleiner als 5000 kB ist, was aber nicht passieren kann, da du ja immer nur in die Datei hineinschreibst, aber nie etwas löschst. Ist es wirklich das, was du erreichen willst?
Kommunikation über globale Variablen ist übrigens pfui, und Kommunikation zwischen Threads über globale Variablen ist doppelt pfui. Nimm lieber
Queue.Queue.
Du solltest nicht im selben Thread von COM1 lesen und in eine Datei schreiben. File-IO ist
blocking und sollte in einem eigenen Thread laufen, damit du nicht COM1 blockierst, sondern so schnell wie möglich wieder von dort lesen kannst.
Außerdem liefert
os.path.getsize() die tatsächliche Größe der Datei auf der Festplatte, aber es ist nicht automatisch sichergestellt, dass schon alles in der Datei gelandet ist, was du hineingeschrieben hast, da File-IO
buffered ist. Der Puffer wird erst geleert und alles daraus auf die Festplatte geschrieben, wenn die Datei geschlossen wird. Da du die Datei aber nicht für jeden Schreibvorgang erneut öffnen und danach wieder schließen möchtest, mußt du den Puffer nach jedem Schreibvorgang explizit mittels
file.flush() und
os.fsync(file.fileno()) leeren.
Und du solltest with-Statements verwenden, damit auch im Falle einer Exception Datei und Port wieder geschlossen werden.
Ich hab's mal umgebaut:
Code: Alles auswählen
import os
from serial import Serial, PARITY_NONE, STOPBITS_ONE, EIGHTBITS
from threading import Thread
from Queue import Queue
PORT_CONFIG = dict(
port='COM1',
baudrate=38400,
parity=PARITY_NONE,
stopbits=STOPBITS_ONE,
bytesize=EIGHTBITS)
LOG_FILE_NAME = 'log.txt'
MAX_LINES = 50
THRESHOLD = 5000
POISON = object()
def read_port(send, port):
try:
for each in xrange(MAX_LINES):
send(port.readline())
finally:
send(POISON)
def write_log(send, receive, logfile):
try:
while True:
data = receive()
if data is POISON:
break
logfile.write(data)
logfile.flush()
os.fsync(logfile.fileno())
send(None)
finally:
send(POISON)
def loop_after_threshold_reached(receive, callback):
while True:
info = receive()
if info is POISON:
break
if os.path.getsize(LOG_FILE_NAME) > THRESHOLD:
callback(info)
def some_function(stuff):
print 'Filesize > 5kb', stuff,
if __name__ == '__main__':
with open(LOG_FILE_NAME, 'a') as logfile:
with Serial(**PORT_CONFIG) as port:
data_channel = Queue()
info_channel = Queue()
reader = Thread(target=read_port,
args=(data_channel.put, port))
writer = Thread(target=write_log,
args=(info_channel.put, data_channel.get, logfile))
looper = Thread(target=loop_after_threshold_reached,
args=(info_channel.get, some_function))
reader.start()
writer.start()
looper.start()
reader.join()
writer.join()
looper.join()
Hierbei werden die Schleifen in
write_log() und
loop_after_threshold_reached() immer nur genauso oft durchlaufen, wie in
read_port(). Statt Millionen sinnloser Durchläufe gibt es also nur jeweils 50. Bei jedem Durchlauf könnte eine Dateigröße >= 5000 erreicht sein, aber es wird für jede tatsächliche Dateigröße nur je einmal getestet, nicht millionenmal.
Und übrigens: die letzten drei Zeilen lösen das Problem, nachdem du gefragt hattest.
Und zuletzt noch: deine Namen könnten besser sein. Wenn ich Code lese, möchte ich nicht zuerst wissen, was um für eine Art von Ding es sich handelt, auf das eine Variable verweist, sondern welche Rolle es im Programm spielt. Thread1 und Thread2 sagen gar nichts aus. Was findest du informativer:
oder:
?
In specifications, Murphy's Law supersedes Ohm's.