Multithreading und raw_input()

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
flyer
User
Beiträge: 11
Registriert: Montag 8. Januar 2007, 09:56

Mittwoch 7. Februar 2007, 10:19

Hallo,
ich habe ehrlich gesagt ein ziemlich dringendes Problem. Ich habe mein Programm über Multithreading dargestellt. Es handelt sich um ein kleines Textbasiertes Menue, mit dem ich einige Steuerungen machen will.
Wenn hier z.b. das Scheduling als eigener Thread gestartet wird kommt man zurück in das Menue und die Abfrage des nächsten Menüpunktes mache ich mit raw_input(). Währenddessen sollte ansich der Scheduling Thread im Hintergrund parallel die aktuelle Uhrzeit mit den Startzeiten der einzelnen Task vergleichen und diese evtl. starten.
Irgendwie schließen sich aber der raw_input() und das Multithreading aus, sobald ich das Menue beende, startet der Scheduling Thread alle Tasks, die er eigentlich hätte schon gestartet haben müssen.
Kann mir einer von Euch die Zusammenhänge hier erklären....müsste man evtl. statt raw_input() eine andere Lösung finden ??

Ich wäre Euch mächtig danbar für einen Tip, da ich im Moment etwas auf dem Schlauch stehe.

Grüße
Flyer
BlackJack

Mittwoch 7. Februar 2007, 10:51

Kannst Du mal ein minimales Programm mit dem Problem posten?
flyer
User
Beiträge: 11
Registriert: Montag 8. Januar 2007, 09:56

Mittwoch 7. Februar 2007, 11:09

Code: Alles auswählen

def main()
    SchedulerEvent=threading.Event()
    MenueEvent=threading.Event()
    JR=JobReader()
    Utility=Util()
    JobManager=JobControl(JR,Utility)
    Schedul=Scheduler(Utility,JobManager,SchedulerEvent)
    Menue=Menues(JobManager,Utility,Schedul,MenueEvent,SchedulerEvent)
    Menue.start()

JobManager,Schedul und Menue sind Klassen von threading.Thread abgeleitet

innerhalb von Menue gibt es folgende passage:

    def run(self):
        while(True):
            if self.MenueEvent.isSet():
                break
            else:
                t=0
                self.showMenue('initial')
                time.sleep(1)
                if t==0:
                    [b]MenuePkt=raw_input('Eingabe: ')[/b]
                    t+=1
                if MenuePkt== '1':
                    if self.showMenue('startJobs'):
                        self.Schedul.start()
                elif MenuePkt=='2':
                    if self.showMenue('stopJobs'):
                        # stoppen der Jobs
                        if self.JobManager.existRunJobs():
                            for stopTask in self.JobManager.Task.TaskListe:
                                self.JobManager.JobStop(stopTask)
                        else:
                            print "Es liegen keine Jobs zum stoppen vor !"
                            time.sleep(3)
                            
                elif MenuePkt=='3':
                    print 'starten eines Jobs'
                    if self.showMenue('startSingleJob'):
                        while(True):
                            # starten eines Jobs
                            print "Folgende Jobs sind verfügbar:"
                            index=0
                            jobMap=dict()
                            for job in TMDict['Job'].keys():
                                try:
                                    desc=TMDict['Job'][job]['Description']
                                except:
                                    desc=' '
                                print " %s \t Job: %s %s Desc:%s" %(index,job,Utility.getSpace(job),desc)
                                jobMap[index]=job
                                index +=1
                            print "\n\t\t\t a \t abbrechen"
                            print "\n"
                            Job=raw_input("Job-Nr: ")
                            #Prüfung gültige Job-Nr einbauen
                            if Job in ['a','A']:
                                break
                            if int(Job) in range(0,index):
                                print "Job %s wird gestartet" %jobMap[int(Job)]
                                for task in TMDict['Job'][jobMap[int(Job)]]['TaskList']:
                                    self.JobManager.createEvents('SingleTask',jobMap[int(Job)]+'.'+task)
                                    self.JobManager.JobStart('SingleTask',jobMap[int(Job)]+'.'+task)
                                break
                            else:
                                print "Keine gültige Job-Nr !"
                                time.sleep(1)
                                os.system('cls')                

D.h. innerhalb des Menue Threads wird das Scheduling als Thread aufgerufen.
Ich hoffe es macht es etwas transparenter. Ich habe mir mal angesehen was es für Alternative zu raw_input() gibt. raw_input() erwartet erst die Eingabe und arbeitet solange nicht weiter, aus dem Modul msvcrt gibt es wohl die Funktion getch(), aber die liefert mir nicht das eingegebene Zeichen zurück, kann aber sein das mein Test noch nicht erfolgreich war.

Freu mich auf Hilfe von Euch...byee

Flyer
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 7. Februar 2007, 13:15

flyer hat geschrieben:Freu mich auf Hilfe von Euch...
Ich hingegen freu mich über ein lauffähiges Programm - ich denke es hat hier keiner Lust erstmal deinen Code zu nehmen und daraus ein lauffähiges Programm zu basteln - das dauert viel zu lange, womöglich länger als die Lösung zu finden.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
flyer
User
Beiträge: 11
Registriert: Montag 8. Januar 2007, 09:56

Mittwoch 7. Februar 2007, 13:26

nicht so kleines Config-File aus dem Daten gelesen werden.
Ich geb dir aber recht das man aus diesem Fragment schwerlich was erkennen kann.

Vielleicht doch erstmal eine generelle Frage vorweg.
Stoppt die Verabeitung von Threads wenn in irgendeinem Thread mit raw_input() eine Eingabe erwartet wird, die anderen Threads scheinen dann keine Aktion mehr zu machen.
Daher war meine Idee mit dem Modul msvcrt und dessen getch() zu arbeiten da hier kein Enter abgewartet wird, aber das Verhalten hier ist auch merkwürdig.
Bei folgenden Code

Code: Alles auswählen

import msvcrt

while 1:
    if getch() == 'z':break
    print 'still run'
würde ich erwarten, das die ganze Zeit 'still run' geprintet wird, bis
ich das Zeichen z eingebe. Leider "brummt" die Schleife aber weiter,
woran liegt das??

Grüße
Flyer
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 7. Februar 2007, 13:48

flyer hat geschrieben:

Code: Alles auswählen

import msvcrt

while 1:
    if getch() == 'z':break
    print 'still run'
würde ich erwarten, das die ganze Zeit 'still run' geprintet wird, bis
ich das Zeichen z eingebe.
Ich würde da eher einen NameError erwarten, weil der Name ``getch`` unbekannt ist. Mangels ``msvcrt``-Modul kann ich dir aber nicht sagen, warum das an der Stelle nicht funktionioert, auch wenn man das korrigiert.

Überigsn, seit Python 2.2.1 nutzt man ``while True:``, weil das klarer ist: "Solange Wahr" statt "Solange Eins".
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Mittwoch 7. Februar 2007, 13:53

Habe auch mal raw_input und threads kombiniert:

Code: Alles auswählen

import threading
import time

class T1(threading.Thread):
    def run(self):
        while True:
            print "Spam", self
            time.sleep(1)

class T2(threading.Thread):
    def run(self):
        while True:
            print "Eggs", self
            time.sleep(2)

while True:
    r = raw_input("Eingabe (1, 2, q): ")
    if r == "1":
        T1().start()
    if r == "2":
        T2().start()
    if r == "q":
        break;

print "Menue zuende..."
Funktioniert eingentlich erstmal so, wie erwartet. Sobald ich eine Zahl eigebe, startet der entprechende Thread.
flyer
User
Beiträge: 11
Registriert: Montag 8. Januar 2007, 09:56

Mittwoch 7. Februar 2007, 14:26

Hi Leonidas,
ich hatte vergessen, das ich bei sowas immer mit from xx import * arbeite...daher hatte ich auch den NameError nicht.
True oder '1' finde ich eher einen Formsache, in Testroutinen nutze ich da mal kurz die 1, in Programmen ist da das Schlüsselwort "True" schon eher angesagt.

Hi Rebecca,
ich hatte noch etwas vergessen und zwar rufe ich in den Threads noch die Funktion subprocess auf, da ich hierüber Windows exe aufrufe und die PID in einer internen Verwaltung halte.
Vielleicht ist das übel auch eher im subprocess zu suchen, da ich im Taskmanager beobachtet habe, das zu dem genannten Zeitpunkt wo der Thread hätte loslegen sollen ein kurzer Prozess in der Taskliste erschien und wieder verschwand.

Hhhmmmm, im Moment grübele ich immernoch und weiß noch nicht wie ich damit umgehen soll. Erstmal vielen dank an alle...vielleicht fällt Euch ja noch etwas ein.

byeee

Flyer
BlackJack

Mittwoch 7. Februar 2007, 17:23

Lass auf jeden Fall das mit den *-Imports bleiben. Da kannst Du Dir wirklich schwer auffindbare Fehler einhandeln. Nämlich das Du irgendwo einen Namen benutzt, der nicht aus dem Modul stammt das Du denkst, sondern aus einem das danach importiert wurde. Wenn Du das in Deinen Modulen grundsätzlich so machst und auch den Inhalt dieser Module wieder mit * importierst, dann geht der Spass sogar über mehrere Ebenen.
Antworten