Programm Kontrolle

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ohne mir alles genauer angeguckt zu haben: WTF soll das hier immer:

Code: Alles auswählen

def description():
        '''
        Kontrollfunktion für Start von Programmen.
        - Übergabe der aktuellen PID des Auftrags-Modul
        ...
        '''

def start_bestellorder():
    def start_description():
        '''
        Einstiegs- und Kontrollfunktion der Auftragsabwicklung.
        Ziel dieser Funktion, ist das kontrollierte Starten des Moduls
        ...
        '''
Du definierst Funktionen, die nichts tun, aber einen Docstring haben... was bezweckst Du damit?

Dann gibt es wieder andere Stellen, wo Du anstelle eines Docstrings normaler Kommentare hinschreibst...

Das sind doch einfach solche "Kleinigkeiten", bei denen man sich schon fragt, wieso Du da nicht mehr Sorgfalt walten lässt.

Den Rest habe ich mir nicht en detail angeguckt - mir fehlt da mittlerweile komplett die Übersicht über den Anwendungsfall und was das ganze eigentlich soll.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Grau. En. Voll. Wirklich. "True in dialog_result", wobei dialog_result global sein muss, die komischen description-funktionen ohne inhalt, voellig leere try/except-Konstrukte, wegfangen von richtig heftigen Programmier-Fehlern wie ImportError. Mein Rat: wegschmeissen. Neu machen.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Code: Alles auswählen

else:
            try:
                pass
            except OSError:
                pass
WAT. Das ist wohl die umständlichste Weise eine leere Zeile zu schreiben. Nein, nichtmal ein ``pass`` Statement, dieser ganze Code kann weg ohne Ersatz und es funktioniert haargenau gleich wie davor auch.

Ich meine, das kannst du doch nicht ernst gemeint haben? Die Klasse ist einfach nur seltsam, die Dscription-Funktion einfach bizarr, wie kommst du darauf, Code auf diese Art zu strukturieren? Und die ganzen Tipps zu System-Globalen PID-Dateien hast du völlig ignoriert, wozu schreibe ich das überhaupt, wenn du das total ignorierst?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

deets hat geschrieben:Mein Rat: wegschmeissen. Neu machen.
Hm... das klingt wenig motivierend, daher will ich es mal umformulieren: Priorität auf das *Lernen* legen. Bisher unzulänglich verstandene Dinge versuchen sich zu erarbeiten und *konsequent* umzusetzen. Das Thema Exceptions hatte ich - iirc sogar in diesem Thread (!) - Dir doch mal lang und breit versucht nahe zu bringen. Und nun taucht da schon wieder ein leeres `except` auf...

Dafür würde ich den Fokus weg von (meiner Meinung nach) Nebenkriegsschauplätzen a la GUI und Kontrolle, dass nur eine Instanz davon laufen darf, auf Dinge wie den grundsätzlichen Aufbau, Ablauf und die verwendeten Datenstrukturen und Backends legen.

Sofern ich das noch überblicke geht es doch nach wie vor um das Thema Kataloge im weitesten Sinne. Dafür musst Du versuchen endlich mal ein "neutrales" Format zu schaffen, welches Du auf eine sinnvolle Art und Weise (relationale DB z.B., ggf. auch gerne JSON) abzulegen. Der bisherige Ansatz mit CSV-Dateien, die zig verschiedene Ausnahmen beinhalten und ständig von einem in das andere Format konvertiert werden, ist imho Kern des ganzen Übels. Da fehlt es dann primär auch an einer sinnvollen *internen* Darstellung von Daten. Geeignete Klassen würden da schon einiges helfen.

Hat man da eine gute Grundlage geschaffen, sollte man vieles auch einfach mit *einfachen* CLI-Tools erledigen können. Von mir aus kann man dann auch einfache Tk-Oberflächen schaffen. Ich würde aber nicht versuchen, einen komplexe Workflows in ein Tk-GUI pressen zu wollen. Damit überhebt man sich vermutlich, zumal, wenn einem in Sachen OOP zu viele Grundlagen fehlen.

Imho hangelst Du Dich momentan von einem Problem zum nächsten und weisst nicht genau, wo Du eigentlich hin willst. Vielleicht reicht es Dir, dieses konkrete Problem *einmal* zu lösen und das ganze - inkl. Python - danach nie wieder anzufassen. Wenn Du jedoch grundsätzlich Python lernen willst *und* zudem Programme so schreiben willst, dass diese wartbar und später auch erweiterbar beliben, dann musst Du einfach die Grundlagen *verinnerlichen*. Dazu gehören einfach Dinge wie das Verständnis über die grundlegenden Datenstrukturen, über Funktionen, Klassen, wie man mit Exceptions umgeht usw. Momentan bist Du zu sehr auf das Lösen eines speziellen Problems "versessen", dass Du bereits erlerntes vergisst, weil Du schnell dieses eine Problem lösen willst und dann irgend wie "schluderst" oder sonst wie zum Ziel "rennst", ohne bekannte Dinge dauerhaft zu berücksichtigen und das Verständnis für diese zu festigen.

Natürlich kommt man ohne Motivation nicht zum Ziel. Es ist auch nicht schlimm, wenn man Code komplett weg wirft und zurück zur Konzeption geht, weil man erkennt, dass das so nicht hinhaut. Oder aber man erlernt während der Entwicklung neue Fertigkeiten, so dass einem selber der alte Code und dessen Struktur nicht mehr überzeugt. Insofern mag es ja ok sein, dass Du so weit gekommen bist; aber imho wäre nun der richtige Schritt, alles noch mal neu und von Anfang an *konsequent* und *strukturiert* neu aufzubauen.

Du wirst hier immer Hilfe erhalten, wenn Du zeigst, dass Du lernwillig bist - im Moment gibst Du uns implizit das Feedback, dass Du Tipps nicht aufgreifst und ungeachtet der mahnenden Beiträge auf ein Ziel zu sprintest. Damit wird die konstruktive Beteiligung auf Deine Threads eher sinken... zumindest bei den Regulars hier.

Nicht falsch verstehen: Ich will Dich nicht niedermachen, sondern Dich ermutigen, Deine Methodik beim Lernen und Umsetzen umzustellen :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
deets

Hyperion hat geschrieben:
deets hat geschrieben:Mein Rat: wegschmeissen. Neu machen.
Hm... das klingt wenig motivierend
Ja, stimmt. Haette ich vielleicht weicher formulieren koennen. Aber es ist auch fuer mich (und ich denke da bin ich nicht alleine, wenn ich zB Leonidas Post ansehe) demotivierend zu sehen, dass trotz zig Iterationen hier sich keinerlei Verbesserung einstellt. Ratschlaege werden ignoriert, es wird weitergeprokelt, bis irgendwas irgendwie klappt. Das kann man ja so machen - aber dann immer wieder um Kritik zu bitten ist dann auch unnoetig.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@deets: hehe... ja, ich habe mir ja deswegen mal die Mühe gemacht, einen erklärenden Thread zu formulieren ;-) Es muss ja auch nicht jeder hier motivieren - ich hab irgend wie eine Sympathie zum OP :-) Aber ich kann Deinen Beitrag komplett verstehen...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Bin über die vielen Rückmeldungen, nach dieser kurzen Zeit überrascht und freue mich darüber.

Hyperion, Du hattest mir mal mit den DOC-Strings ein Beispiel gegeben, dies hieß damals 'def foo():', daher habe ich dies so abgeleitet. Vielleicht habe ich Dich da auch falsch verstanden.
Ich werde dann dies Funktion herausnehmen und die DOC-Strings ohne aufstellen.
Ich habe auch Verständnis dafür, daß Dir und den Anderen, die Übersicht über den Anwendungsfall inzwischen fehlt. Es wurde ja auch schon viel geschrieben und ich bin nicht der Einzige hier, mit dem Ihr Euch befasst. :wink:
Deine vorletzten Post habe ich auch gelesen, verzeih wenn ich hier jetzt nicht auf alles eingehe. Ich weiß, daß ich Eure Nerven strapaziere, was aber in keinster Weise meine Absicht ist. Dies ist für mich auch verständlich, daß von Eurem Wissenstand in Bezug was ich hier abliefere, Resignation bei Euch sich breit macht.
Mein Ziel ist es, die Bestellorder für Lieferanten (Auftragsverwaltung), die per Mail und FTP versendet werden, nochmals neu durch zu arbeiten. Der erste Schritt war für mich jetzt prog_check.py. Auch wenn da noch manches verbesserungswürdig ist, habe ich hier ein Modul, das mehrfach verwendet werden kann und auch wirklich funtkioniert. Ich bin schon wieder dabei, ein paar Kleinigkeiten darin zu optimieren.

deets, dialog_result ist global, siehe hier

Code: Alles auswählen

from gui_dialog import dialog_result, dialog_func, showinfo_func
Wegschmeißen und neu machen, ich manchmal nicht verkehrt, aber auch nicht immer da Richtige ... :wink:

Leonidas, Danke für Deinen Tip, der Rest ist wirklich unnötig! :wink:
Auch wenn die Klasse etwas seltsam ist, denke ich daß ich zukünftig dies verbessern kann und weitere kleine Lernfortschritte machen werde.
'Tipps zu System-Globalen PID-Dateien hast du völlig ignoriert', sprichst Du da beispielsweise 'dbus' an?
Vielleicht fehlt auch mir langsam etwas der Überblick ...
deets

Mir ist *klar*, dass das global war. Der Punkt ist, dass es das nicht sein sollte.

Und ich bleibe dabei: mit dem jetzt erworbenen Wissen um das eigentliche Problem das ganze *NEU* zu machen ist besser. Du hast offensichtlich dermassen viele Artefakte alten rumprobierens in deinem Code - das wird in meinen Augen nix mehr.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ok, hier nochmal mein neues geändertes Modul prog_check.py.
Außer den DOC-Strings, habe ich auch die Funktion 'def prog_list(self):' und die darauf folgende Funktion 'def prog_check(self):' abgeändert.

Code: Alles auswählen

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

### Import Module
import os, re, signal
from gui_dialog import dialog_result, dialog_func, showinfo_func



# Programmaufruf
class prog_control(object):
    '''
    Kontrollfunktion für Start von Programmen.
    - Übergabe der aktuellen PID des Auftrags-Modul
    - Überprüfung, ob das Auftrags-Modul evtl. schon läuft
    - Freigabe des Auftrags-Modul, wenn kein Doppelstart vorliegt
    - Auswahldialog bei Doppelstart
    -- Auswahlmöglichkeit Abbruch (Nein), schon gestartetes Auftrags-Modul läuft weiter
    -- Auswahlmöglichkeit Beenden (Ja), schon gestartetes Auftrags-Modul wird beendet
    Bei schon gestartetem Programm, wird ein nochmaliges starten
    des gleichen Programmes verhindert. Gleichzeitig wird ein
    Dialog zum Beenden des aktiven Programmes angeboten.
    :param programm: string, Programmnamen
    :param titel: string, Programm-Bezeichnung
    :param pid_current: int, aktuelle PID des gestarteten Programmes
        '''

    def __init__(self, programm, titel, pid_current):
        self.programm = programm
        self.titel = titel
        self.pid_current = pid_current

        # Die ersten 15 Stellen des Programmnamens
        self.prog_short = '{}'.format(self.programm[:15])

        self.prog_pid = ''
        self.pid_ok = False
        self.pid_diff = 0
        self.wert1 = ''
        self.wert2 = ''

    def prog_list(self):
        '''Erstelle Listen über aktive IDś'''

        self.wert1 = os.popen('ps -u $USER 2>/dev/null').readlines()
        self.wert2 = os.popen('ps -u 2>/dev/null').readlines()

    def prog_check(self):
        '''
        Überprüfe ob das Programm schon läuft
        und gebe die aktuelle PID aus.
        '''

        for i in self.wert1:
            if self.prog_short in i:
                line = re.sub('^[ ]+', '', i)
                self.prog_pid = line.partition(' ')[0]
                self.pid_ok = True
                break

        if not self.pid_ok:
            for i in self.wert2:
                if self.programm in i:
                    line = re.sub('[ ]+', '-', i)
                    self.prog_pid = line.partition('-')[2]
                    self.prog_pid = self.prog_pid.partition('-')[0]
                    self.pid_ok = True
                    break
                else:
                    self.pid_ok = False

        if self.prog_pid is not None and self.pid_current is not None:
            self.pid_diff = (int(self.prog_pid) - int(self.pid_current))
        else:
            self.pid_diff = 1

    def prog_evaluation(self):
        if self.pid_ok is True and self.pid_diff is not 0:
            info = '''Programm läuft schon mit PID: %s
Möchten Sie dieses Programm beenden?''' % self.prog_pid
            dialog_result.clear()
            dialog_func(self.titel, info)

            if True in dialog_result:
                os.kill(int(self.prog_pid), signal.SIGTERM)
                os.kill(int(self.pid_current), signal.SIGTERM)
                info = 'Programm mit PID: %s wird beendet' % self.prog_pid
                showinfo_func(self.titel, info)
                sys.exit(1)
            else:
                os.kill(int(self.pid_current), signal.SIGTERM)
                sys.exit(1)
        else:
            pass

if __name__ == "__main__":
    f = prog_control(programm, titel, pid_current)
    f.prog_list()
    f.prog_check()
    f.prog_evaluation()
deets, vielleicht könntest Du auch mal mit Code argumentieren, was so wirklich katastrophal ist.
Oder Du zeigst mir, wie Du es machen würdest. :wink:
deets

Ganz einfach. Was du machst ist sowas in der Art hier:

Code: Alles auswählen

globale_variable = []

def zeig_nen_dialog():
      globale_variable[:] = []
      globale_variable.append(True) # oder False, je nach Dialog-Ergebnis

zeige_nen_dialog()
if True in globale_variable:
    pass # tu nix??!?!?
elif False in globale_variable:
    # tu was
warum nicht einfach

Code: Alles auswählen

def zeige_nen_dialog():
      return True # oder eben False

if not zeige_nen_dialog():
   # tu was
Kuerzer, zu verstehen ohne den Zustand globaler Variablen im Kopf zu jonglieren, und auch noch einen toten Code-Ast entfernt...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nobuddy hat geschrieben: Hyperion, Du hattest mir mal mit den DOC-Strings ein Beispiel gegeben, dies hieß damals 'def foo():', daher habe ich dies so abgeleitet. Vielleicht habe ich Dich da auch falsch verstanden.
Ein Docstring soll Module, Klassen oder Funktionen (Methoden) beschreiben. Dazu muss man nicht "künstlich" noch eine leere Funktion erstellen, die man dokumentiert ;-) Ich kann mir kaum denken, dass das bei mir der Fall war. Wenn Dir so etwas unklar ist, dann solltest Du so etwas noch mal in einem Tutorial nachlesen - ich bin ja keine Python-Referenz :-D

Du musst bei Beispielen auch drüber nachdenken; was hast Du Dir denn für Dich selber erklärt, wieso man Docstrings wohl in dieser Art aufstellen muss:

Code: Alles auswählen

def function():
    def senseless_other_function():
        """
        Hier schreiben wie die Doku zu `function` hin, obwohl wir uns
        doch in einer anderen befinden... *wunder*
        """
    # und hier wird dann die Funktionalität von `function` hingeschrieben
Du musst doch *spätestens* beim Coden drüber nachdenken, wieso Du so etwas hinschreibst. Du wusstest ja sicher, dass `def` eine Funktion einleitet. Du schreibst nun zweimal `def` hin... wie hast Du Dir das erklärt? Irgend wie müssten sich ja die beiden `defs` unterscheiden...

Über so etwas musst Du doch nachdenken / nach gedacht haben!?

So etwas meine ich mit meinen Anmerkungen, dass Du *sorgfältig* vorgehen musst. Denn dann wäre Dir doch aufgefallen, dass das alles "komisch" aussieht und irgend wie nicht passt... wenn Du nicht selber auf die eigentliche Lösung gekommen wärst.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Ok, verstehe was Du mir damit zeigen willst.

Ich muß jetzt nur nochmal kurz nach haken.
Die globale Variable 'dialog_result', kommt aus dem Modul gui_dialog und gibt die Eingabe aus dem Tk-Dialog-Fenster wieder, die ich ja dann in dem Modul 'prog-check' weiter verarbeite. Die direkten Werte des Dialog-Fensters, sind aber nicht True oder False, sondern 'yes' oder 'no'. Lässt sich dies dann auch so umsetzen?

Das Modul gui_dialog.py:

Code: Alles auswählen

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

### Import Module
from Tkinter import *
import tkMessageBox

# Programm
dialog_result = set()

def dialog_func(title, info):
    root = Tk()
    DialogFenster = tkMessageBox.askquestion(title, info)
    dialog_result.clear()    # Liste leeren
    if DialogFenster == 'yes':
        result = True
    elif DialogFenster == 'no':
        result = False
    dialog_result.add(result)
    root.destroy()


def showinfo_func(title, info):
    root = Tk()
    tkMessageBox.showinfo(title, info)
    root.destroy()
Noch eine andere Frage.
Was ist mit der Klasse, soll diese weg oder habe ich Dich da falsch verstanden mit 'seltsam?

Hyperion, ich gebe mir Mühe zukünftig sorgfältiger vorzugehen!
Zuletzt geändert von Nobuddy am Mittwoch 13. Juni 2012, 14:53, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nobuddy hat geschrieben: Hyperion, ich gebe mir Mühe zukünftig sorgfältiger vorzugehen!
Ich wollte Dir nur mal aufzeigen, was bei Deinem bisherigen Vorgehen nicht so toll ist. Ich hätte mir gewünscht, dass Du wirklich verstehst, was ich Dir mit dem negativen Resultat des Verarbeitens von Tipps aus diesem Forum aufzeigen wollte. Leider gehst Du darauf nicht ein...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Nobuddy: Du möchtest also das deets Dir Dein Programm neu schreibt. Netter Versuch, aber es wird nach der bisherigen Erfahrung nur dazu füheren dass Du einen weiteren Code-Baustein in Dein Programm einfügst, den Du nicht wirklich verstehst.

Das fängt schon mit so grundlegenden Sachen wie Funktionen an, die Du anscheinend nicht verwenden kannst oder willst. Diese ganze Klasse ist zum Beispiel unsinnig, weil es einfach Code-Abschnitte mit Namen sind, die auf globalen Variablen operieren, wo man eigentlich ganz normale Funktionen verwenden könnte und sollte. Die Variablen sind technisch gesehen nicht ``global`` aber eben semantisch. Alles von Modulebene in eine Klasse zu verschieben entfern ``global`` nur kosmetisch, aber nicht *wirklich*. Genau wie dieses abenteuerliche Konstrukt den Rückgabewert eines Dialogs auf Moduleben in eine Liste zu stecken. Das ist auch eine globale Variable die nicht sein sollte.

Dann so tolle Namen wie `wert1` und `wert2`. Wo man nicht weiss wofür die eigentlich stehen und die auch noch überraschenderweise an Listen gebunden werden und nicht an „Skalare”. Den Name `i` in einer Schleife an etwas anderes als ganze Zahlen zu binden geht auch gar nicht.

Ich bin mir ziemlich sicher von `os.popen()` wurde zu gunsten von `subprocess` schon mindestens einmal abgeraten. Und ich hatte auch schon mal das `psutil`-Modul zum Arbeiten mit PIDs emfohlen. Und hast Du ``ps -u`` mal auf der Konsole ausprobiert? Oder ist das der Grund warum Du die Fehlerausgabe nach ``/dev/null/`` umlenkst um die Fehlermeldung zu ignorieren statt sie zu vermeiden?

Was hast Du Dir dabei gedacht: ``self.prog_short = '{}'.format(self.programm[:15])``‽ Und was bei diesem `re.sub()`/`partition()`-Unsinn.

Mir ist auch die Funktionsweise von `prog_check()` nicht wirklich klar‽ Es wird ``ps`` für den Benutzer aufgerufen, und dann geprüft ob das Programm darin gelistet wird. Dann das gleiche für „alle” Prozesse, wo das Programm auf jeden Fall drin ist (wenn es nicht in der kurzen Zeitspanne zwischen den beiden ``ps``-Aufrufen beendet wurde). Ob man bei diesem zweiten Durchlauf den selben Prozess findet, oder vielleicht einen anderen Prozess, der das selbe Programm ausführt, ist reiner Zufall!

In der zweiten Schleife ist übrigens der ``else``-Zweig offensichtlich überflüssig.

Welchen Sinn die Bildung der Differenz von zwei PIDs haben soll, wenn man doch beide PIDs schon als Attribute hat und deshalb trivial feststellen kann ob die *gleich* sind, ist mir auch ein Rätsel.

`prog_evaluation()` fängt mit einem Programmfehler an: Man prüft nur garantierte Singletons mit ``is`` und ``is not`` auf einen konkreten Wert. Wenn man Werte vergleichen will und nicht Objektidentitäten, dann verwendet man ``==`` und ``!=``. Wenn die Funktion so korrekt arbeitet, ist das nur Zufall beziehungsweise ein Implementierungsdetail des konkreten Python-Interpreters. Wobei literale Wahrheitswerte sollte man sowieso nicht vergleichen, denn da kommt ja doch nur wieder ein Wahrheitswert heraus. Also hätte man auch gleich den Ausgangswert verwenden können.

``else: pass``‽ Ernsthaft‽

Ausprobiert hast Du das als Programm auch nicht, denn das hätte Dir einen `NameError` um die Ohren gehauen.
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

BlackJack, ich fange mit Letzterem an.
Das besagte Modul, habe ich ausgiebig auf Linux Kubuntu 12.04, zuerst unter Geany, dann der Konsole getestet und ist nun unter $HOME/bin verknüpft. Es funktioniert prima, startet Module und überprüft vorher, ob diese schon evtl. laufen. Bei schon laufendem Modul, habe ich die Möglichkeit über ein Dialog-Fenster, das laufende Modul zu beenden oder weiter laufen zu lassen. Ein zweites Mal, wird das gleiche Modul jedenfalls nicht gestartet.

Das mit "``else: pass``‽ Ernsthaft‽", erklärt sich so. Dieses Modul prog_check wird von dem Modul bestellorder_lieferant aus aufgerufen. Wenn kein Doppelstart des Modules bestellorder_lieferant vorliegt, wird dieses gestartet, deshalb pass. Sonst öffnet sich ein Dialog-Fenster ... siehe oben.

Den Programmfehler in `prog_evaluation()` werde ich korrigieren, Danke für Deine Erklärung dazu.

Bei der Bildung der Differenz von zwei PIDs, hatte ich anfangs Probleme beim vergleichen. Dies könnte jetzt aber nicht mehr der Fall sein, was ich überprüfen und wenn möglich ändern werde.

Du hast Recht, 'In der zweiten Schleife ist übrigens der ``else``-Zweig offensichtlich überflüssig', da ich ja am Anfang den Wert False zugwiesen habe, Danke.

Soweit Du auch Linux verwendest, rufe einmal in der Konsole 'ps -u' und 'ps -u $USER' auf. Du wirst sehen, du erhälst zwei verschiedene Ausgaben auch im Format. Daher auch das mit 're.sub', um an die PID ran zu kommen. Ich habe festgestellt, daß je nach dem von wo aus ich das Programm aufrufe, einmal in der Ausgabe von 'ps -u' und einmal in 'ps -u $USER' enthalten ist. Das mit 'self.prog_short = '{}'.format(self.programm[:15])' ist erforderlich, da die eine Ausgabe nur die ersten 15 Stellen des Programmnamens ausgibt.

Das mit dem `psutil`-Modul werde ich mir anschauen und die Änderung dann vornehmen. Wird wohl wesentlich einfacher sein, als mein jetziges Konstrukt. Sorry und Danke nochmals für den Hinweis!

Ja mit der Namensgebung, habe ich als meine Schwierigkeiten, evtl. wäre pid_scalar1 und pid_scalar2 besser. Ich wußte daß Listen der falsche Ausdruck war, leider war mir der Richtige (Scalar) nicht bekannt.

Anhand aus jetziger Sicht, werde ich das Modul prog_check nochmals neu machen, vielleicht kann ich Euch dann ein bisschen überraschen...

Daß mir deets oder ein Anderer von Euch, mein Programm schreibt, ist keine gute Lösung und das will ich auch nicht, denn ich muß es ja auch selbst verstehen ...

Hyperion, bitte nimm das nicht negativ auf, wenn ich nicht gleich darauf eingehe.
Ich werde mir darüber Gedanken machen und melde mich dann, versprochen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ein `else: pass` kann niemals ein anderes Verhalten bewirken, als wenn man dieses einfach weglässt :!:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Nobuddy
User
Beiträge: 994
Registriert: Montag 30. Januar 2012, 16:38

Hyperion, Danke für die Info, das war mir nicht klar.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hyperion hat geschrieben:Ein `else: pass` kann niemals ein anderes Verhalten bewirken, als wenn man dieses einfach weglässt :!:
Beim Weglassen dreht sich der Stromzähler nicht mehr ganz so schnell...
Nobuddy hat geschrieben:Hyperion, Danke für die Info, das war mir nicht klar.
Dann stellt sich natürlich die Frage, was du geglaubt hast was ein else:pass bewirkt.
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

EyDu hat geschrieben: Beim Weglassen dreht sich der Stromzähler nicht mehr ganz so schnell...
:mrgreen: YMMD!
EyDu hat geschrieben: Dann stellt sich natürlich die Frage, was du geglaubt hast was ein else:pass bewirkt.
Genau das wäre wieder eine ähnliche Situation, wie die von mir lang ausgebreitete Sache mit den Docstrings ;-) Das *Nachdenken* beim Code und hinterfragen, ob man Konstrukte wirklich verstanden hat ist eben wichtig. Aber dazu wird sich Nobuddy ja noch äußern, wie er versprach :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Nobuddy: Das Modul selbst hast Du nicht als Programm ausgeführt, denn das funktioniert nicht.

Und egal wie oft Du das ausprobierst, heisst das nicht, dass es fehlerfrei ist. Dann hattest Du halt nie den Fall, dass der andere Prozess *nach* dem neuen von ``ps`` gelistet wurde. So etwas kann aber vorkommen und zumindest bei meinem Rechner kommt das in der Praxis auch regelmässig vor. Und dann funktioniert es so nicht mehr.

Probleme beim Vergleichen hattest Du, weil Du Dir nicht klar machst *was* Du da eigentlich vergleichst. Natürlich sind eine Zahl und eine Zeichenkette *niemals* gleich. Das sind Grundlagen. Beides in `int()` zu wandeln, wobei das bei der Zahl eine Nulloperation ist — da kommt genau das gleiche Objekt wieder heraus, das kann man sich also sparen — und dann voneinander *abzuziehen* statt es *dann* einfach zu vergleichen, zeigt wieder Dein tiefes Unverständnis was da eigentlich passiert in dem Code.

Ich verwende Linux, und ich *habe* die beiden ``ps``-Aufrufe ausprobiert. Darum weiss ich ja auch so genau dass ``ps -u`` fehlerhaft ist. Denn da wird neben den Daten noch eine deutliche Warnung ausgegeben, dass der Aufruf so syntaktisch für ``ps`` nicht in Ordnung ist::

Code: Alles auswählen

bj@s8n:~$ ps -u
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
bj         342  0.0  0.1 251288  3992 pts/3    Sl   Jun10   0:00 /usr/bin/python
bj         361  0.0  0.1 263076  4100 pts/3    Sl   Jun10   0:00 /usr/bin/python
bj         375  0.0  0.0      0     0 pts/3    Z    Jun10   0:00 [sh] <defunct>
bj        3115  0.0  0.0   7240   284 pts/2    Ss   May29   0:00 /bin/bash
bj        3116  0.0  0.0   7580  2820 pts/3    Ss   May29   0:03 /bin/bash
bj        3117  0.0  0.0   7248   488 pts/1    Ss+  May29   0:00 /bin/bash
bj        3118  0.0  0.0   7272   404 pts/4    Ss+  May29   0:01 /bin/bash
bj        3119  0.0  0.0   7256   408 pts/5    Ss+  May29   0:01 /bin/bash
bj        5118  0.0  0.2  77416  7884 pts/2    Sl+  May29   0:07 /usr/bin/python
bj       11006  0.0  0.0   2712  1060 pts/3    R+   15:26   0:00 ps -u
bj       18788  0.0  0.0   7272   436 pts/6    Ss+  Jun04   0:00 /bin/bash
Und hier sieht man auch, dass die PIDs und die Reihenfolge in der Anzeige nicht der Reihenfolge der Startzeit eines Prozesses entsprechen muss. Obwohl der Prozess mit der PID 342 sechs Tage nach dem Prozess mit der PID 18788 gestartet wurde, wird er zuerst aufgelistet. Und das passiert nicht nur bei „ewig” laufenden Servern, sondern auch bei virtuellen und realen Rechnern die nicht heruntergefahren, sondern nur in einen „Suspend”-Modus versetzt werden. Und es kann auch bei Rechner vorkommen, wo viele Prozesse gestartet und beendet werden. Aus welchen Gründen auch immer. Eine robuste Lösung muss mit so etwas umgehen können.
Antworten