Variable über "Subprocess" in anderem Script benutzen.

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
fabius
User
Beiträge: 1
Registriert: Mittwoch 12. Juni 2019, 09:59

Hey,
Ich will meinem Programm mit tkinter ein GUI hinzufügen, doch wenn ich tkinter direkt in mein Script einbinde läuft der Code der nach der mainloop kommt nicht.
Also habe ich eine neue Datei angelegt und in dieser dann Tkinter benutzt, und in meinem "Main" Script habe ich das neue Script dann mit subprocess.Popen eingebunden.
Das Fenster hat sich geöffnet, und mein Programm lief, also erstmal alles gut, aber als ich dann Variablen von meinem 1. Script in mein 2. Script "übertragen" wollte ging das nicht (zumindest die Anleitungen die ich gefunden habe haben nicht funktioniert).
Ich hab meinen Code mal grob zusammengefasst:

"Main" Script:

Code: Alles auswählen


import subprocess
import speech_recognition as sr
from time import ctime
import time
import os

test = "test"
subprocess.Popen(["python", "Pfad der Datei", test])

def aufnahme():
    r = sr.Recognizer()
    with sr.Microphone() as source:
        print("Bereit")
        audio = r.listen(source)

    eingabe = ""

    try:
        eingabe = r.recognize_google(audio, language="de")
        print("DU: " + eingabe)
    except sr.UnknownValueError:
        print("Fehler")
    except sr.RequestError as e:
        print("Fehler")

    return eingabe




def commands(eingabe):
    if "test" in eingabe:
        print("TEST")

stopp = ""
while stopp != "Stopp":
    eingabe = aufnahme()
    stopp = eingabe
    commands(eingabe)

2. Script:

Code: Alles auswählen


from Tkinter import *
fenster = Tk()
fenster.title = "Test"
fenster.geometry("600x800")
text = Label(fenster, text = test)
text.pack()
fenster.mainloop()

In diesem Fall will ich also die Variable test in das 2. Script bekommen.

Ich hoffe ihr könnt mir helfen, und vielen Dank im Voraus!
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Einfache Antwort: das geht nicht.

Um dein Problem zu loesen hast du zwei Moeglichkeiten:

- du benutzt Threads. Dann ist alles in einem Programm. Du musst allerdings aufpassen, weil man aus Threads die GUI-Elemente NICHT manipulieren darf. Wir diskutieren das hier permanent, einfach mal ein bisschen durch das Tkinter Unterforum stoebern.
- statt subprocess benutz multiprocessing. Da mit kannst du einen Unterprozess erzeugen, der per einfacher Datenstruktur wie einer Queue erlaubt, Daten vom Prozess zu bekommen. Auch hier ist die Integration mit Tkinter nicht total trivial, du wirst entweder die after-Funktion oder create_file_handler bemuehen muessen.
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@fabius: Ein paar Anmerkungen zum gezeigten Hauptskript:

Das wichtigste vorweg: Man fängt keine neuen Programme mehr mit Python 2 an: https://pythonclock.org/

Ausser `speech_recognition` und `subprocess` wird keiner der Importe irgendwo verwendet.

Kryptische Abkürzungen sollte man vermeiden. Einbuchstabige Namen sind auch nur ganz selten sinnvolle Namen.

Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm gehört dort nicht hin, schon gar nicht durch andere Definitionen unterbrochen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Das in der Hauptschleife der gleiche Wert immer an zwei Namen gebunden wird, ist unnötig kompliziert und verwirrend.

Wenn man eine ``while``-Schleife hat, bei der man vor der Schleife einen Namen an einen ”Dummy”-Wert binden muss, dann ist das in der Regel idiomatisch besser als ”Endlosschleife” (``while True:``) ausgedrückt, die mit einem Test in der Schleife und ``break`` verlassen wird.

Funktionsnamen beschreiben üblicherweise die Tätigkeit die die Funktion ausführt. `aufnahme()` und `commands()` sind keine Tätigkeiten. An der Stelle fällt auch auf, das kein sinnvolles Muster zu erkennen ist nach welchen Kriterien Du Namen Deutsch oder Englisch gewählt hast. Am besten bleibt man komplett bei Englisch.

Das der `RequestError` an den Namen `e` gebunden wird, wird nirgends genutzt.

Da beide Ausnahmen gleich behandelt werden, kann man das auch in *einem* ``except`` erledigen.

Ungetesteter Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3
import subprocess

from speech_recognition import (
    Microphone, Recognizer, RequestError, UnknownValueError
)


def listen_for_answer():
    recognizer = Recognizer()
    with Microphone() as source:
        print('Bereit')
        audio = recognizer.listen(source)

    answer = ''
    try:
        answer = recognizer.recognize_google(audio, language='de')
        print('DU:', answer)
    except (UnknownValueError, RequestError):
        print('Fehler')

    return answer


def process_answer(answer):
    if 'test' in answer:
        print('TEST')


def main():
    test = 'test'
    subprocess.Popen(['python', 'Pfad der Datei', test])

    while True:
        answer = listen_for_answer()
        if answer == 'Stopp':
            break
        process_answer(answer)


if __name__ == '__main__':
    main()
Zum GUI-Programm: Bezüglich dem was auf Modulebene (nicht) gehört gilt das gleiche wie beim Hauptskript.

Sternchen-Importe sind Böse™. Gar nicht erst angewöhnen so etwas.

Die Fenstergrösse gibt man in der Regel nicht vor, die ergibt sich aus dem Inhalt des Fensters.

Den Fenstertitel legt man so ähnlich fest wie Du das gemacht hast, aber eben nicht *so*.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@fabius: es gibt viele Methoden der Interprocess-Kommunikation. Ich sehe auch im gezeigten Code gar keinen Versuch der Kommunikation.
Wenn Du schon von einer Anleitung sprichst, solltest Du diese auch angeben, damit wir ein Bild davon haben, was Du versucht hast.

Üblicherweise benutzt man Pipes. Das lesen der Pipe geht in der GUI über `createfilehandler`.
Beispiel: tkinter-read-async-subprocess-output.py
Benutzeravatar
__blackjack__
User
Beiträge: 14044
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wobei die ganze Komplexität mit einem extra Prozess hier IMHO nicht wirklich Sinn macht.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Antworten