Multiprocessing bei getrennten Prozessen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast keine einfache Frage gestellt. Du hast zwei Dateien erwaehnt, in denen irgendwas passiert, das du nicht zeigst. Damit kann man dir keinen Weg zeigen, wie das mit multiprocessing geht. Das geht nicht so, dass man da einfach zwei Zeilen hier postet, und dann funktioniert das. Das muss *EIN* Programm werden, welches dann mit dem multiprocessing-Modul mehrere Prozesse erstellt.

Und deine Begruendung ist immer noch nicht schluessig. Du hast ein mentales Model von dem was da passiert oder nicht, dass halt schlicht und ergreifend nicht passt. Wenn du wirklich parallelle Audio- und Midi-Ausgabe hast, musst du eh ganz anders vorgehen, indem du selbst eine Audio-Anwendung bist, welche die MIDI-Ereignisse mit Zeitstempeln versieht in einem Thread, und im Audio-Thread dann mit einer um die Gesamtlatenz des Systems korrigierten verschoben auf diese Ereignisse reagiert. All das hat mit mehreren Prozessen NICHTS zu tun.

Aber das du dich verrenst ist jetzt wahrlich oft genug gesagt worden. Viel Erfolg bei deinem Projekt.

Nachtrag: ich schrieb MIDI, meine aber auch GPIO mit. Event ist event.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich würde das ja noch mal umschreiben wollen, weil die beiden Funktionen ja im Grunde das gleiche tun und man `args` dann auch tatsächlich etwas sinnvolles mitgeben könnte 🙂:

Code: Alles auswählen

#!/usr/bin/env python3
import multiprocessing
import time


def ausgeben(label, items):
    for item in items:
        print(label, item)
        time.sleep(0.1)


def main():
    for arguments in [("z=", range(100)), ("x=", reversed(range(100)))]:
        multiprocessing.Process(target=ausgeben, args=arguments).start()


if __name__ == '__main__':
    main()
Und jetzt das ganze mal mit Threads:

Code: Alles auswählen

#!/usr/bin/env python3
import threading
import time


def ausgeben(label, items):
    for item in items:
        print(label, item)
        time.sleep(0.1)


def main():
    for arguments in [("z=", range(100)), ("x=", reversed(range(100)))]:
        threading.Thread(target=ausgeben, args=arguments).start()


if __name__ == '__main__':
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

Sirius3 hat geschrieben: Freitag 20. März 2020, 15:31 Dass ein wirkliches Gleichzeitig auf einem Raspi ohne Echtzeitbetriebssystem nicht geht, wurde Dir ja schon gesagt, was Du aber anscheinend ignorierst.
Bisher hast Du nur nicht-funktionierenden Python-Code gezeigt, der mit Deinem realen Problem so viel zu tun hat, wie eine Anleitung zur Fahrrad-Reparatur, wenn man ein kaputtes Flugzeug hat.
Läßt sich aber auch trivial in ein funktionierendes Beispiel umschreiben:

Code: Alles auswählen

import multiprocessing
import time

def raufrechnen():
    for i in range(0, 100):
        print('z=', i)
        time.sleep(0.1)

def runterrechnen():
    for j in range(100, 0, -1):
        print('x=', j)
        time.sleep(0.1)

if __name__ == '__main__':
    p1 = multiprocessing.Process(target=raufrechnen, args=())
    p2 = multiprocessing.Process(target=runterrechnen, args=())
    p1.start()
    p2.start()
Hi Sirius,
oberaffengeil, das sieht so aus, wie ich mir das gedacht habe. Ich werde jetzt versuchen, meine beiden Prozesse hier einzubauen und zum Laufen zu kriegen. Wenn das gelungen ist, melde ich mich wieder.

Allen Beteiligten ein herzliches Dankeschön. Ich werde die hier gemachten Empfehlungen berücksichtigen. Ich bin nicht so drauf, dass ich Äußerungen von erfahreneren Menshen ignoriere. Aber es wäre für mich unbefriedigend gewesen, wenn ich diesen Weg hier nicht ausprobiere.
We´ll see.
Bleibt gesund und Dank an alle!
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dieses Beispiel von Sirius3 ist ein absolutes Minimalbeispiel, welches den entscheidenden Teil - den Austausch von Nachrichten - NICHT enthaelt. Es ist also nur ein modicum besser, als die Prozesse einfach selbst zu starten. Aber wenn's schee macht.

(Ist im uebrigen keine Kritik an dem Beispielgeber. Mit ohne nix kann man auch nur mit ohne nix machen).
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

Liebe Musikfreunde,
jetzt habe ich alles zusammengebaut und habe das Problem,
dass eine Variable nicht einfach angenommen wird.

Wenn ich im Kopf z = 2 definiere (das ist eine Voreinstellung, damit aus einem Excel-Sheet nicht die Kopfzeilen gelesen werden), da meckert der Raspi (Line 37: Redefining name 'z' from outer scope (line 32)).

Was mache ich da falsch?
Im Kurzscript (in dem es nur um das Abspielen der Songs geht) funktioniert das anstandslos.

Kann jemand helfen?

Noch eine Bitte: Ich wuerde euch gerne das Script hier anheften, weiss aber nicht, wie das geht. Vielleicht hat jemand einen Tipp. Ich kopier das jetzt einfach mal hier rein,aber dann stimmen die Einrckungen gleichwieder nicht.

Beste Gruesse
Micki

Code: Alles auswählen

from __future__ import print_function
from tkinter import *
import pygame.mixer
pygame.init()
pygame.mixer.init(44100, 16, 2, 4096)
pygame.mixer.music.set_volume(0.6)
sound = pygame.mixer.Sound('/home/pi/rpituto/wav/mitest.wav')
import RPi.GPIO as GPIO
import time
import openpyxl
wb = openpyxl.load_workbook("mperf1.xlsx")
sheet = wb.get_sheet_by_name("Tabelle1")
import mido
from mido import Message
mido.get_input_names()
mido.get_output_names()
from collections import deque
import multiprocessing


GPIO.setmode(GPIO.BCM)
GPIO.setup(5, GPIO.IN)  # Song +    grau
GPIO.setup(22, GPIO.IN) # Song -    lila
GPIO.setup(27, GPIO.IN) # Scene +   gruen
GPIO.setup(17, GPIO.IN) # Scene -   weiss
GPIO.setup(4, GPIO.IN)  # Vol + 10  braun
GPIO.setup(12, GPIO.IN) # Vol - 10  blau
GPIO.setup(25, GPIO.IN) # Eff +1    schwarz
GPIO.setup(24, GPIO.IN) # Eff -1    gelb
GPIO.setup(23, GPIO.IN) # transpose     violett
GPIO.setup(18, GPIO.IN) # transpose     rot
z=2                     # 2 wegen der Kopfzeilen im Excel-Sheet

def tasten():
    while True:      
        if GPIO.input(5) == 0:    # Song +1
            z += 1                # Zeilennummer  +1 
            print('SongNr=', sheet["A" + str(z+1)].value, sheet["C" + str(z+1)].value)
            pygame.mixer.music.load('/home/pi/rpituto/wav/' + sheet['C' + str(z+1)].value)
            pygame.mixer.music.play(0)
            time.sleep(0.5)
        if GPIO.input(22) == 0:   # Song -1
            z -= 1                # Zeilennummer  -1 
            print('SongNr=', sheet["A" + str(z+1)].value, sheet["C" + str(z+1)].value)
            pygame.mixer.music.load('/home/pi/rpituto/wav/' + sheet['C' + str(z+1)].value)
            pygame.mixer.music.play(0)
            time.sleep(0.5)
      
  
#------------------------SPIELEN-------------------------
             
def spielen():
    while True:
        inport = mido.open_input('Impulse:Impulse MIDI 1 28:0')
        outport = mido.open_output('E-MU Xmidi 2x2 MIDI 1')
        msglog = deque()
        echo_delay = 1
        msg = inport.receive()
        msglog.append({"msg": msg, "due": time.time() + echo_delay})
        outport.send(msglog.popleft()["msg"])

if __name__ == '__main__':
    p1 = multiprocessing.Process(target=tasten, args=())
    p2 = multiprocessing.Process(target=spielen, args=())
    p1.start()
    p2.start()
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Setze deinen Code bitte in Code-Tags, damit die Einrückungen erhalten bleiben. Die werden eingefügt, wenn man unter "Vollständiger Editor & Vorschau" auf den </>-Button klickt.

Dann solltest du den Code vorher aufräumen. Importe gehören an den Anfang des Codes. Ohne irgendwelche Codezeilen dazwischen.

Ist das etwas Python 2.x? Das ist tot. Tu das weg.
Python 2.x wird seit Anfang des Jahres nicht mehr unterstützt. Da werde ich keinen Code mehr für heile machen, es sei denn es gibt einen wirklich, wirklich guten Grund das noch zu verwenden.

Zeichenketten stückelt man nicht mit + zusammen sondern benutzt seit Python 3.6 sogenannte f-Strings.

Auf Modulebene haben nur Konstanten etwas verloren.

Ich sehe nicht, warum hier multiprocessing nötig ist.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sparrow hat dir schon gesagt, wie man die Formatierung hier macht - ich habe das jetzt mal fuer dich erledigt.

Das der Code kein multiprocessing benoetigt, haben wir auch schon mehrfach erwaehnt. Und das wird jetzt um so klarer. Kleiner Pro-Tipp: wenn man schnell Musik abspielen will, sollte man sie nicht erst laden, bevor man sie benutzt. Und erst recht nicht eine riesige Buffergroesse mit ~100ms Latenz waehlen.

Wenn du globalen Zustand benutzen willst, musst du global benutzen. (Ja, das macht man eigentlich nicht, aber der TE will ja mit dem Kopf durch seine Wand).
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@sparrow: Ein __future__-Import funktioniert auch mit Python3 und da tkinter klein geschrieben ist, ist das Python3.

@Micki: Die Importe sind so durcheinander, dass man da nicht durchsteigt. tkinter wird importiert aber nicht benutzt, zudem sollte man keine *-Importe benutzen. `as` ist dazu da um einen Namen umzubenennen, GPIO wird aber gar nicht umbenannt.
Alles auf oberster Ebene sollte da nicht stehen, vor allem, wenn Du multiprocessing benutzt. Variablennamen sollten aussagekräftig sein, und aus mehr als einem Buchstaben bestehen.

Wenn Du die PINs benutzt, gib ihnen auch aussagekräftige Namen, statt nur Nummern.
Statt Code zu kopieren benutzt man Funktionen, um Wiederholungen zu vermeiden.
Man programmiert keine Busy-Loops sondern nutzt die passenden Event-Detect-Mechanismen.

Code: Alles auswählen

import time
import openpyxl
import threading
from pathlib import Path
from collections import deque
from queue import Queue
import pygame.mixer
from RPi import GPIO
import mido
from mido import Message

NEXT_SONG = 5   # Song +    grau
PREV_SONG = 22  # Song -    lila
SONG_PATH = Path('/home/pi/rpituto/wav')
EXCEL_FILENAME = "mperf1.xlsx"


def play_song(sheet, row):
    song_nr = sheet[f"A{row}"].value
    song_name = sheet[f"C{row}"].value
    print(f'SongNr={song_nr} {song_name}')
    pygame.mixer.music.load(str(SONG_PATH / song_name))
    pygame.mixer.music.play(0)
    time.sleep(0.5)

def tasten():
    try:
        GPIO.setmode(GPIO.BCM)
        GPIO.setup([NEXT_SONG, PREV_SONG], GPIO.IN)
        queue = Queue()
        GPIO.add_event_detect(17, GPIO.RISING, queue.put, 500)
        GPIO.add_event_detect(27, GPIO.RISING, queue.put, 500)

        pygame.init()
        pygame.mixer.init(44100, 16, 2, 4096)
        pygame.mixer.music.set_volume(0.6)
        sound = pygame.mixer.Sound(str(SONG_PATH / 'mitest.wav'))
        wb = openpyxl.load_workbook(EXCEL_FILENAME)
        sheet = wb.get_sheet_by_name("Tabelle1")
        current_row = 3
        while True:
            pin = queue.get()
            if pin == NEXT_SONG:
                current_row += 1
                play_song(sheet, current_row)
            elif pin == NEXT_SONG:
                current_row -= 1
                play_song(sheet, current_row)
    finally:
        GPIO.cleanup()

def spielen():
    mido.get_input_names()
    mido.get_output_names()
    while True:
        inport = mido.open_input('Impulse:Impulse MIDI 1 28:0')
        outport = mido.open_output('E-MU Xmidi 2x2 MIDI 1')
        msglog = deque()
        echo_delay = 1
        msg = inport.receive()
        msglog.append({"msg": msg, "due": time.time() + echo_delay})
        outport.send(msglog.popleft()["msg"])

def main():
    threading.Thread(target=tasten).start()
    spielen()

if __name__ == '__main__':
    main()
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: hast du das getestet? Ich hatte in der Vergangenheit Probleme mit pygame und Threads. Kann aber sein, dass das durch die pygame.init in dem Thread geht, aber man sollte sicher gehen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Keine Ahnung, natürlich nicht getestet.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

`PREV_SONG` wird nicht wirklich verwendet, an einer Stelle dafür wohl fälschlicherweise `NEXT_SONG`. Die Pinwerte passen nicht zusammen. Erkannt werden „Scene +/-“ aber getestet wird auf „Song +/-“.

Ich denke Probleme mit Pygame aus einem anderen Thread als dem Hauptthread könnten dadurch zustande kommen, dass es sich im weitesten Sinne um ein GUI-Rahmenwerk handelt, und andere Rahmenwerke auch so eine Einschränkung haben. Das liesse sich hier einfach lösen in dem man einfach die andere Funktion in einen weiteren Thread verlegt. Das `pygame.init()` braucht man aber IMHO gar nicht, man kann auch nur das gewünschte Subsystem von SDL initialisieren.

Bei Threads würde ich in der Regel die `daemon`-Option mitgeben, dann wird das abbrechen des Programms einfacher.

`sound` in `tasten()` wird definiert aber nirgends verwendet.

Bei `spielen()` verstehe ich die ersten beiden Funktionsaufrufe nicht mit deren Rückgabewert nichts gemacht wird.

Die Ports zur Ein- und Ausgabe werden *in* der Schleife ständig geöffnet um *eine* Nachricht zu verarbeiten. Warum passiert das nicht nur einmal vor der Schleife?

Zudem werden die Ports nie geschlossen. Da die eine `close()`-Methode haben, wird es sicher Backends geben bei denen das nicht so toll ist wenn man die nicht tatsächlich sicher wieder schliesst. `Port`-Objekte sind Kontextmanager. Input-Ports sind zudem iterierbar über die Nachrichten.

Was dann da mit der Queue angestellt wird ist einfach nur überflüssig.

Code: Alles auswählen

#!/usr/bin/env python3
import threading
import time
from pathlib import Path
from queue import Queue

import openpyxl
import pygame.mixer
import mido
from RPi import GPIO

NEXT_SONG_PIN = 5  # Song + (grau)
PREVIOUS_SONG_PIN = 22  # Song - (lila)

SONG_PATH = Path("/home/pi/rpituto/wav")
EXCEL_FILENAME = "mperf1.xlsx"


def play_song(sheet, row):
    song_nr = sheet[f"A{row}"].value
    song_name = sheet[f"C{row}"].value
    print(f"SongNr={song_nr} {song_name}")
    pygame.mixer.music.load(str(SONG_PATH / song_name))
    pygame.mixer.music.play(0)
    time.sleep(0.5)


def tasten():
    try:
        GPIO.setmode(GPIO.BCM)
        GPIO.setup([NEXT_SONG_PIN, PREVIOUS_SONG_PIN], GPIO.IN)
        queue = Queue()
        GPIO.add_event_detect(NEXT_SONG_PIN, GPIO.RISING, queue.put, 500)
        GPIO.add_event_detect(PREVIOUS_SONG_PIN, GPIO.RISING, queue.put, 500)

        pygame.init()
        pygame.mixer.init(44100, 16, 2, 4096)
        pygame.mixer.music.set_volume(0.6)
        workbook = openpyxl.load_workbook(EXCEL_FILENAME)
        sheet = workbook.get_sheet_by_name("Tabelle1")
        current_row = 3
        while True:
            pin = queue.get()
            #
            # TODO Make sure the user cannot chose invalid rows without song
            # data.  Best to remove the workbook handling here and in
            # `play_song()` and pass in the songs as list of tuples or similar.
            #
            if pin == NEXT_SONG_PIN:
                current_row += 1
                play_song(sheet, current_row)
            elif pin == PREVIOUS_SONG_PIN:
                current_row -= 1
                play_song(sheet, current_row)
            else:
                assert False, "unexpected pin: {!r}".format(pin)
    finally:
        GPIO.cleanup()


def spielen():
    while True:
        with mido.open_input("Impulse:Impulse MIDI 1 28:0") as inport:
            with mido.open_output("E-MU Xmidi 2x2 MIDI 1") as outport:
                outport.send(inport.receive())


def main():
    tasten()
    threading.Thread(target=spielen, daemon=True).start()


if __name__ == "__main__":
    main()
Letztendlich könnte sogar ohne eigene Threads auskommen, denn auch bei `mido` kann man das erstellen eines Threads der Bibliothek überlassen in dem man beim Input-Port einen Callback angibt der immer aufgerufen wird wenn eine Nachricht rein kommt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

Hammer! Ihr seid Sahne.
Ich bin ja erst seit ein paar Wochen dabei mit Python und Raspi zu arbeiten und habe eine Programmiertradition aus den 70ern in den Knochen. Aber hier kann ich ja viel lernen.
Ich werde das heute Abend mal testen. Zu der Frage "wie programmiert man richtig?" habe ich bestimmt noch viel Fragen.
Ich freue mich auf ein funktionierendes Tool!
Dank an Alle

Update
der erste Test ist erfolgt.
- Das Abspielen der Playbacks laeuft super.
- Im Part "spielen" tut sich leider garnichts. :(
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

Was ich auch noch sagen wollte:
So, wie ich das "spielen"-Script lese, werden die eingehenden Daten ja direkt wieder ausgegeben.

Die Knoeppe haben den Sinn, dass an den Bytes Veraenderungen vorgenommen werden koennen.
z.B. Steckt bei einem Note-Command im ersten (Status-) Byte die Channel#, dass heisst, die Klangfarbe. Im 2. Byte steckt die Tonhoehe und im 3. Byte die Anschlagstaerke. Die wuerde ich bei Bedarf gerne manipulieren koennen (+,- 1 oder 10) und dann anstatt der Originalbytes in die Pipe schicken.
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

sparrow hat geschrieben: Samstag 21. März 2020, 11:34 Setze deinen Code bitte in Code-Tags, damit die Einrückungen erhalten bleiben. Die werden eingefügt, wenn man unter "Vollständiger Editor & Vorschau" auf den </>-Button klickt.
Hi Sparrow,
was sind denn "code-tags" und wo finde ich den "vollständigen Editor & Vorschau"? Ich hab hier nur die normale Vorschau ... Und ich will noch was Script posten ...

Im Übrigen ein herzliches Dankeschön für deine Tips. Mit mehr Erfahrung werde ich bestimmt mal besser :geek:
Beste Grüsse
Micki
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Unter der Schnellantwort gibt es "Vollständerig Editor & Vorschau" und "Absenden".
Nimmst du nicht Absenden kommst du zum vollständigen Editor.
Und wen du dort </> drückst, wirst du die Code-Tags erkennen.
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

Thanks fuer die Erklaerung! Das ist der "spielen-Part" solo. Der laeuft bei mir. Ich hab noch keine Veraenderungen vorgenommen ...

Code: Alles auswählen

from tkinter import *
import pygame.mixer
pygame.init()
pygame.mixer.init(44100, 16, 2, 4096)
pygame.mixer.music.set_volume(0.6)
sound = pygame.mixer.Sound('/home/pi/rpituto/wav/mitest.wav')
import RPi.GPIO as GPIO
import time
import openpyxl

import mido
from mido import Message
mido.get_input_names()
mido.get_output_names()
mido.backends.rtmidi

from collections import deque
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN) # ANO   schwarz
GPIO.setup(24, GPIO.IN) # ASO   gelb
GPIO.setup(23, GPIO.IN) # transpose     violett
GPIO.setup(18, GPIO.IN) # transpose     rot

inport = mido.open_input('Impulse:Impulse MIDI 1 28:0')
outport = mido.open_output('E-MU Xmidi 2x2 MIDI 1')

msglog = deque()
echo_delay = 1

while True:
    if GPIO.input(25) == 0:           # ANO
        ano = Message('control_change', channel=0, control=123, value=0)
        outport.send(ano)
        time.sleep(0.5)
        print('befehl', ano)

    if GPIO.input(24) == 0:           # ASO
        aso = Message('control_change', channel=0, control=120, value=0)
        outport.send(aso)
        time.sleep(0.5)
        print('befehl', aso)
# -----------------------------------------------------------------
    if GPIO.input(23) == 0:           # transpose +1
        send(control_change, 0, 120, 0)
        time.sleep(0.5)
    if GPIO.input(18) == 0:           # transpose -1
        t -=1
        channel = t
        time.sleep(0.5)

    msg = inport.receive()
    msglog.append({"msg": msg, "due": time.time() + echo_delay})
    outport.send(msglog.popleft()["msg"])
Zuletzt geändert von Micki am Samstag 21. März 2020, 17:13, insgesamt 2-mal geändert.
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Dein Code muss zwischen die Tags. Also [ code]dein code[ /code] Nur ohne die Leerzeichen.
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

Ich habe mich da oben wohl etwas falsch ausgedrückt.
Mit "Ich habe nichts veraendert" wollte ich sagen, dass ich das Script noch nicht umschreiben konnte (Mangels Ahnung).
Es waere unheimlich toll, wenn Ihr mir helfen könntet, das Script von Blackjack auch im 2. Teil ans laufen zu kriegen 🙏
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Micki: `msglog` und die letzten drei Zeilen sind doch total sinnlos. Deswegen hatte ich das ja auch alles rausgeworfen, denn unterm Strich bleibt da nur das vom `inport` gelesene in den `outport` schreiben übrig.

Und da sind Zeile drin die keinen Sinn machen. Zum Beispiel die beiden `get_*_names()`-Aufrufe und die Zeile die direkt danach folgt. Warum steht das da?

Die beiden Transpose-Tasten können nicht funktionieren weil in beiden ``if``-Zweigen die das jeweils behandeln `NameError` ausgelöst werden.

Die Tasten insgesamt können auch nur funktionieren wenn über `inport` regelmässig Nachrichten reinkommen, und auch in einer gewissen Frequenz, denn sonst hängt die Endlosschleife am blockierenden `receive()`-Aufruf.

Grundsätzlich ist da wieder das Thema vom Anfang: Das sollte man nicht durch ein irgendwie geartetes verbinden von zwei bestehenden Programmen lösen, sondern eine sinnvolle Gesamtlösung programmieren. Beispielsweise eine eigene Ereignisschleife in die sowohl GPIO-Taster als auch Midi-Nachrichten vom `inport` ein eine `queue.Queue` gespeist werden, wodurch man dann auch gleich die sichere Übertragung von verschiedenen Threads zu dem Thread der das dann abarbeitet gewährleistet hat. Und sowohl `RPi.GPIO` als auch `mido` können selber Threads starten die Callbacks für eingetretene Ereignisse aufrufen können.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Micki
User
Beiträge: 34
Registriert: Freitag 20. März 2020, 09:17

Die Fragmente, die Du bemängelst, sind Überbleibsel aus der Entstehungsphase die ich (noch) nicht rausgeschmisseb habe, weil sie im nächsten Schritt wieder gebraucht werden. Mir ist klar, dass das für Dich störend wirkt.

Was die Strategie angeht, bin ich ja mittlerweile mit Euch/Dir eins. Mir fehlt eben noch Erfahrung.

Vielen Dank nochmal für Deine Überarbeitung. Das ist ja alles Arbeit.
Könntest Du vielleicht so nett sein und den "spielen"-Part nochmal anschauen. Wenn der läuft, kann ich mich erst mal wieder selbst beschäftigen. Außerdem muss ich Euren "Stil" verstehen lernen.
Am Ende werde ich Euch das Produkt auf alle Fälle zeigen.
Antworten