Problem mit Audio CDs

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.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Wenn ich mein Programm so schreibe, wie ich es mir vorstelle, dann funktioniert es einwandfrei.
Wenn ich es aber so mache, wie man mir es empfiehlt, dann funktioniert es überhaupt nicht.

Hier ein Teilauszug meines Programmes:

Code: Alles auswählen

lindsey_stearling_disc = read_audio_disc(join(mymusicpath,'Lindsey Sterling'))
dosomething_with_music(lindsey_stearling_disc)

# Hier wuerde ich gerne ein bestimmtes python statement einfuegen. Aber einige sind strikt dagegen
# del lindsey_stearling_disc

indila_disc  = read_audio_disc(join(mymusicpath,'Indila'))
dosomething_with_music(indila_disc)

# Ja und dabei crasht dann bereits mein Sytem mit nur 1 GB Hauptspeicher. Aber begreifen wollen das anscheinend einige nicht

# Hier wuerde ich gerne wieder das bestimmte python statement einfuegen. Aber einige sind strikt dagegen
# del indila_disc

soha_disc  = read_audio_disc(join(mymusicpath,'Soha'))
dosomething_with_music(soha_disc)

# del soha_disc
Hier lese ich jeweils eine Audio CD in eine Variable ein und mache dann damit etwas. Zuerst hatte ich gedacht, dass ich immer denselben Namen für die Variable nehme, damit der Speicher dann aufgeräumt wird. Da hat man mir aber gesagt, dass das nicht nötig wäre, denn Python kümmert sich schon automatisch darum. Wenn ich mit einer CD etwas gemacht habe, brauche ich sie nicht mehr im Speicher. Da hatte ich mir gedacht, dass ich den Speicher auch wieder freigebe. Aber dann hat man mich sehr geschimpft und dann so etwas geschrieben: Du betreibst del als Mikromanagement, und Mikromanagement ist unsinnig und damit del auch. Oder dass das Speichermanegement in Python wäre und dass ich davon gefälligst die Finger lassen soll. Oder dass ich damit nur dem Garbage Collector die Arbeit erschwere, der das automatisch macht.

Also, wenn ich es so mache, wie ich es mir gedacht hatte, dann funktioniert das Programm einwandfrei, wie man hier sieht:

Code: Alles auswählen

picuntu@picuntu:~/PythonCD$ python3 loadwav.py
499.88232 MB
677.04672 MB
449.71416 MB
picuntu@picuntu:~/PythonCD$
Und weil mein Computer nur 1 GB RAM hat, war mir vollkommen klar, dass ich die zweite CD nicht mehr laden kann. Und genauso ist es auch, denn es kommt dann entweder das heraus:

Code: Alles auswählen

picuntu@picuntu:~/PythonCD$ python3 loadwav.py
499.88232 MB
Killed
picuntu@picuntu:~/PythonCD$
Oder das:

Code: Alles auswählen

icuntu@picuntu:~/PythonCD$ python3 loadwav.py
499.88232 MB
Traceback (most recent call last):
  File "loadwav.py", line 42, in <module>
    indila_disc  = read_audio_disc(join(mymusicpath,'Indila'))
  File "loadwav.py", line 18, in read_audio_disc
    tracks=[ read_wav_file(join(mypath,f)) for f in wavfiles ]
  File "loadwav.py", line 18, in <listcomp>
    tracks=[ read_wav_file(join(mypath,f)) for f in wavfiles ]
  File "loadwav.py", line 11, in read_wav_file
    wavdata = w.readframes(wlen)
  File "/usr/lib/python3.2/wave.py", line 253, in readframes
    data = self._data_chunk.read(nframes * self._framesize)
  File "/usr/lib/python3.2/chunk.py", line 134, in read
    data = self.file.read(size)
  File "/usr/lib/python3.2/chunk.py", line 134, in read
    data = self.file.read(size)
MemoryError
picuntu@picuntu:~/PythonCD$
Also ich weiss jetzt nicht mehr weiter, was ich jetzt tun soll. Wenn ich del nehme, dann funktioniert es, wenn ich del nicht nehme, ist es völlig klar, dass das Programm crasht. Aber das will hier keiner einsehen und man will mich so hinstellen, als ob ich uneinsichtig oder bescheuert wäre, weil ich einfach nicht kapieren will, dass man del oder einen Ersatz hier nicht braucht.
BlackJack

@Alfons Mittelmeyer: Man braucht hier kein ``del`` weil Dir auch schon mehrfach gesagt wurde das so etwas nicht auf Modulebene gehört. Wenn Du eine Funktion schreibst die eine CD verarbeitet, dann verschwinden die lokalen Namen nach deren Aufruf von selbst und die automatische Speicherbreinigung kümmert sich um den Speicher.

Zumal kein vernünftiger Programmierer das da nicht als Schleife schreiben würde.

Du *bist* uneinsichtig. Wir stellen Dich nicht nur so hin.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Genau,das hatten wir schon mal: http://wiki.python-forum.de/FAQ#Was_sin ... en_Code.3F
Kein Code auf Modulebene. Dort stehen nur Konstanten- und Klassen und Funktionsdefinitionen. Nutzte: if __name__ == "__main__":

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Also sowas:

Code: Alles auswählen

def process_cd(cd_name):
    disc = read_audio_disc(join(mymusicpath,cd_name))
    dosomething_with_music(disc)


if __name__ == "__main__":
    cds = (
        'Indila', 'Lindsey Sterling', 'Soha', #...
    )
    for cd in cds:
        process_cd(cd)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Das würde dann so aussehen:

Code: Alles auswählen

# ...

def main():
    for cd_name in ['Lindsey Sterling', 'Indila', 'Soha']:
        dosomething_with_music(read_audio_disc(join(mymusicpath, cd_name)))


if __name__ == '__main__':
    main()
Allerdings kann das bei dem Verhältnis von Datenmenge und Hauptspeicher knapp werden wenn die Speicherbereinigung nicht nachkommt. Denn es ist nicht garantiert ob und wann Objekte abgeräumt werden, *egal was man als Programmierer macht*. In dem Fall ist entweder die Hardware oder eben Python nicht geeignet für diese Aufgabe.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jens hat geschrieben:Genau,das hatten wir schon mal: http://wiki.python-forum.de/FAQ#Was_sin ... en_Code.3F
Kein Code auf Modulebene. Dort stehen nur Konstanten- und Klassen und Funktionsdefinitionen. Nutzte: if __name__ == "__main__":
Sorry, das ist kein Modul, sondern ein Script. Es könnten auch unterschiedliche Scripts sein, die über Standardinput hereinkommen und die dann für Python nicht als unterschiedliche Scripts erkennbar sind. Aber jetzt hört endlich einmal mit Eurem Schwachsinn auf. Wer war es, der das Löschen von Speicher nicht auf Scriptebene gelöst hatte? Das war ich. Und wer hatte dann weitergemacht und solchen Unsinn behauptet, dass Python von alleine globale Variablen aufräumen würde? Wer hatte immer wieder Beweise gefordert dass so etwas crasht, obwohl jeder vernünftige Mensch das erkennen sollte? Das war ganz bestimmt nicht ich. Wollte Euch nur den behaupteten Schwachsinn mal deutlich vor die Augen führen. Und wer noch immer nicht glaubt, dass so etwas crasht. Hier ist der Code für ein Directory, welches Unterdirectories mit WAV Dateien enthält:

Code: Alles auswählen

import wave

from os import listdir, system
from os.path import isfile, join


def read_wav_file(name): 
	w = wave.open(name,'rb')
	wlen = w.getnframes()
	wavdata = w.readframes(wlen)
	w.close()
	return wavdata

def read_audio_disc(mypath='.'):
	onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
	wavfiles = [ f for f in onlyfiles if f[-4:] == '.wav' ]
	tracks=[ read_wav_file(join(mypath,f)) for f in wavfiles ]
	return tracks

def dosomething_with_music(musicdisc):
	# Nur ein Bespiel. Natuerlich macht man mit einer Disc mehr
	memory = 0
	for f in musicdisc: memory += len(f)
	print(memory/(1000000),'MB')

# ================================================================
# Bitte den Pfad anpassen

mymusicpath = "//media/picuntu/My Passport/Music [WAV]/"
# ================================================================

lindsey_stearling_disc = read_audio_disc(join(mymusicpath,'Lindsey Sterling'))
dosomething_with_music(lindsey_stearling_disc)

# Hier wuerde ich gerne ein bestimmtes python statement einfuegen. Aber einige sind strikt dagegen
# del lindsey_stearling_disc

indila_disc  = read_audio_disc(join(mymusicpath,'Indila'))
dosomething_with_music(indila_disc)

# Ja und dabei crasht dann bereits mein Sytem mit nur 1 GB Hauptspeicher. Aber begreifen wollen das anscheinend einige nicht

# Hier wuerde ich gerne wieder das bestimmte python statement einfuegen. Aber einige sind strikt dagegen
# del indila_disc

soha_disc  = read_audio_disc(join(mymusicpath,'Soha'))
dosomething_with_music(soha_disc)

# del soha_disc
Vielleicht endlich eingesehen, dass so etwas crasht. Aber wie gesagt, ich habe alles zusammen, um meinen GuiCreator und anderes optimal zu schreiben. Und werde auf irgendwelche Sinnlosigkeiten oder Angriffe nicht mehr eingehen.
BlackJack

@Alfons Mittelmeyer: Ein Skript ist ein Modul.

Skripte kommen nicht über die Standardeingabe herein. Diesen Unsinn hattest Du schon einmal behauptet, auf Nachfrage wolltest Du das dann explizit nicht belegen weil Dir das zu viel Arbeit gemacht hätte. Du sagtest Du müsstest Firmen befragen wie die das denn machen. WTF!?

Niemand hat behauptet globale Variablen würden automatisch aufgeräumt. Das hast Du schonmal versucht zu unterstellen.

Beweise wurden für ganz andere Sachen gefordert. Zum Beispiel die mehrere Millionen Funktionen die kein reales Programm hat und auch nicht dynamisch erstellt. Hier zeigst Du nur das sehr grosse Datenmengen den dafür recht knappen Speicher aus- und überlasten können. Wenn man das nicht sauber und vernünftig programmiert (*ohne ``del``!) dann stürzt das Programm ab. Aber auch wenn man sauber und vernünftig programmiert kann das in Python abstürzen mit dieser Konstellation wegen der fehlenden Garantien bei der Speicherverwaltung. Das schreibe ich jetzt schon wieder, und das wirst Du wahrscheinlich auch *wieder* ignorieren. Und wunderst Dich dann das Du mindestens als uneinsichtig rüberkommst. :roll:

Das Skript hast Du doch auch absichtlich so geschrieben wie das kein normaler Programmierer machen würde. Siehe Jens' und meinen letzten Beitrag, die ohne den *unmöglichen* Versuch manuell Speicher freigeben zu wollen auskommen.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Alfons Mittelmeyer hat geschrieben:
jens hat geschrieben:Genau,das hatten wir schon mal: http://wiki.python-forum.de/FAQ#Was_sin ... en_Code.3F
Kein Code auf Modulebene. Dort stehen nur Konstanten- und Klassen und Funktionsdefinitionen. Nutzte: if __name__ == "__main__":
Sorry, das ist kein Modul, sondern ein Script. Es könnten auch unterschiedliche Scripts sein, die über Standardinput hereinkommen und die dann für Python nicht als unterschiedliche Scripts erkennbar sind.
Ob du es nun Modul oder Script nennt, ist egal. Es gehört auf der Ebene kein Code der direkt ausgeführt wird. (Ausnahmen bestätigen die Regel)...

Mir ist erst letztens aufgefallen, das es blöd ist:

Ich hab in DragonPy auf "nose" ( https://nose.readthedocs.org/en/latest/ ) umgestellt...
Der sucht überall nach Test code. Also wird jede Datei importiert... und was passiert wenn auf oberster Ebene Code ist ?!?

Also wurden ein paar "schnelle hack scripte" (Die ich nur temporär brauchte) importiert und ausgeführt und natürlich war das so nicht vorgesehen.

Also immer :!: if __name__ == "__main__": nutzten!
Alfons Mittelmeyer hat geschrieben:Aber jetzt hört endlich einmal mit Eurem Schwachsinn auf.
Kannst du dir bitte mal einen andern Ton angewöhnen. Du suchst Hilfe. Willst also was von "uns". Wenn es allerdings so weiter geht, dann werde ich dich zukünftig einfach ignorieren...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Alfons Mittelmeyer hat geschrieben:Sorry, das ist kein Modul, sondern ein Script.
Damit hast du dich endgültig als ernstzunehmender Diskussionspartner disqualifiziert. Python-Dateien (also solche, in denen Python Code steht und deren Namen auf .py endet), sind Module. Wenn das, wo der Code herkommt, keine Datei ist, dann kann es immer noch ein Modul sein, zB. wenn man das ast Modul aus der Standard-Bibliothek zur Code-Generation hernimmt. Oder einfach nur die Builtin-Funktion compile():

Code: Alles auswählen

>>> s = 'print("hallo")'
>>> c = compile(s, '<string>', 'eval')
>>> c.co_name
'<module>'
Alfons Mittelmeyer hat geschrieben:Und wer hatte dann weitergemacht und solchen Unsinn behauptet, dass Python von alleine globale Variablen aufräumen würde?
Sie werden aufgeräumt, wenn die Namen out-of-scope gehen, also wenn das Script/Modul bendet wird. Wenn man allerdings der Regel folgt, dass auf Modul-Ebene keine Namen außer Importen, Funktionen und Klassen definiert werden, dann gibt es das Problem überhaupt nicht. Wir haben hier also die Situation, dass jemand (d.h. du), beständig etwas kompliziertes tun will, bei dem noch nicht mal garantiert ist, dass es funktioniert, weil er (d.h. du) nicht den einfachen Weg gehen will, der dafür vorgesehen ist.

Der Code, den du gepostet hast, zeigt deutlich, dass du nicht weißt, welche Möglichkeiten Python bietet, sparsam mit Speicher umzugehen. Insbesondere möchtest du dich mit Generator-Funktionen vertraut machen. Giuckstu:

Code: Alles auswählen

import os
import os.path
import wave

def read_wav_file(name):
    with wave.open(name,'rb') as wave_file
        return wave_file.readframes(w.getnframes())

def read_audio_disc(wave_file_path='.'):
    for name in os.listdir(wave_file_path):
        full_name = os.path.join(wave_file_path, name)
        if os.isfile(full_name) and full_name.endswith('.wav'):
            yield read_wav_file(full_name)
In specifications, Murphy's Law supersedes Ohm's.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: Du bist nicht einmal ein schlechter Verlierer. Aber Du würdest noch das Geld Deiner Urenkel beim Poker verzocken, bevor Du vom Tisch aufstehst. Dir wurde schon einmal gesagt, wenn man gegen die Sprache arbeitet, kommt nichts sinnvolles dabei raus. Du definierst drei globale Variablen und sagst damit Python, das brauche ich alles noch. Wie man es sinnvoll und mit lokale Variablen macht, wurde Dir hier nochmal ausführlich gezeigt. Da Du hier aber gar nicht mit ganzen Discs sondern nur mit einzelnen Tracks arbeitest, läßt sich der Speicherbedarf noch weiter reduzieren:

Code: Alles auswählen

import os
import wave
import glob

# ================================================================
# Bitte den Pfad anpassen
MUSIC_PATH = "//media/picuntu/My Passport/Music [WAV]/"
ALBUMS = ['Lindsey Sterling', 'Indila', 'Soha']

def read_wav_file(name):
    w = wave.open(name,'rb')
    wlen = w.getnframes()
    wavdata = w.readframes(wlen)
    w.close()
    return wavdata

def iter_tracks(path):
    for filename in glob.iglob(os.path.join(path,'*.wav')):
        if isfile(filename):
            yield read_wav_file(filename)
 
def dosomething_with_music(tracks):
    # Nur ein Bespiel. Natuerlich macht man mit einer Disc mehr
    memory = sum(len(t) for t in tracks)
    print('{0:.0f}MB'.format(memory/1000000))

def main():
    for album in ALBUMS:
        tracks = os.path.join(MUSIC_PATH, album)
        dosomething_with_music(tracks)

if __name__ == '__main__':
    main()
Natürlich kann man ein Programm schreiben, das die ganze Festplatte einliest und sich dann wundern, warum das nicht klappt, aber das ist wieder kein Beweis, dass Python oder wir zu blöd sind, sondern nur, dass Du (noch) nicht gelernt hast, wie man in Python programmiert.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Dass man ein paar hundert Bytes sparen kann, indem man keine Liste verwenndet, wenn man 600 MB einliest, macht wenig Sinn und deshalb von Speicherverschwendung zu sprechen, ergibt auch keinen Sinn. Dass man natürlich keine gance CD einliest, wenn man nur wissen will, wieviel MB auf der CD sind, ist wohl auch klar. Ebenso klar ist auch, dass man mit einer CD im Speicher eine Menge anfangen kann. Sicher habt Ihr Verständnis dafür, dass ich jetzt keine Audio Anwendung für eine CD im Speicher schreibe. Allerdings mich als Verlierer zu bezeichnen ist ebenso unsinnig. Denn ich habe ja gewonnen. BlackJack und Jens hatten sich eifrig bemüht, zu zeigen, dass es auch anders geht, und man ein del nicht braucht. Und genau das war auch der Sinn, was es aufzuzeigen galt: Speicherverwaltung und Freigabe von Memory in Python geschehen nicht von selber, wie vorher behauptet wurde, sondern man muss entsprechend programmieren.

Die vorgestellten Lösungen waren allerdings auch nicht optimal, denn es geht nicht um Module, sondern um Scripte, um es nochmals in aller Deutlichkeit zu sagen. Der von mir vorgestellte Code war ein Script. Allerdings einen Teil davon könnte man auch als Modul implementieren, nämlich diesen Teil:

Code: Alles auswählen

import wave

from os import listdir, system
from os.path import isfile, join


def read_wav_file(name): 
	w = wave.open(name,'rb')
	wlen = w.getnframes()
	wavdata = w.readframes(wlen)
	w.close()
	return wavdata

def read_audio_disc(mypath='.'):
	onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
	wavfiles = [ f for f in onlyfiles if f[-4:] == '.wav' ]
	tracks=[ read_wav_file(join(mypath,f)) for f in wavfiles ]
	return tracks

def dosomething_with_music(musicdisc):
	# Nur ein Bespiel. Natuerlich macht man mit einer Disc mehr
	memory = 0
	for f in musicdisc: memory += len(f)
	print(memory/(1000000),'MB')

# ================================================================
# Bitte den Pfad anpassen

mymusicpath = "//media/picuntu/My Passport/Music [WAV]/"
# ================================================================
Natürlich sollte es viele Funktionen dafür geben, etwas mit einer Disc zu tun und nicht nur diese: dosomething_with_music

Der Rest waren dann Scripte, wobei nicht unterscheidbar ist, eines oder mehrere. Und bei Scripten geht es darum, was der User entweder als File lädt beim Aufruf von Python oder aber händisch eintippen kann oder sonstwie über Standardinput an Python weiterleitet, oder auch über eval und compile handhabt.

Also es geht darum: Was darf der User eintippen?

Darf er das eintippen?

Code: Alles auswählen

lindsey_stearling_disc = read_audio_disc(join(mymusicpath,'Lindsey Sterling'))
dosomething_with_music(lindsey_stearling_disc)
del lindsey_stearling_disc
Muss er es so eintippen?

Code: Alles auswählen

def function():
    lindsey_stearling_disc = read_audio_disc(join(mymusicpath,'Lindsey Sterling'))
    dosomething_with_music(lindsey_stearling_disc)
function()
Oder sollte er es so eintippen?

Code: Alles auswählen

class UniClass():
    def __init__(self):
        lindsey_stearling_disc = read_audio_disc(join(mymusicpath,'Lindsey Sterling'))
        dosomething_with_music(lindsey_stearling_disc)
UniClass()

# das Folgende tippt der User normalerweise erst ein, nachdem das Vorhergehende fertig ist (könnte auch eine Stunde später sein)

class UniClass():
    def __init__(self):
        indila_disc  = read_audio_disc(join(mymusicpath,'Indila'))
        dosomething_with_music(indila_disc)
UniClass()

# das Folgende tippt der User normalerweise erst ein, nachdem das Vorhergehende fertig ist
# und ob er sich für diese oder jene CD entscheidet und was er um diese Zeit damit machen will, steht von Anfang an auch nicht fest

class UniClass():
    def __init__(self):
        soha_disc  = read_audio_disc(join(mymusicpath,'Soha'))
        dosomething_with_music(soha_disc)UniClass()
UniClass()
Es stellt sich also die wichtige Frage: Wie soll der User das eintippen, damit er nicht gegen Regeln verstößt?
Zuletzt geändert von Alfons Mittelmeyer am Freitag 21. August 2015, 22:00, insgesamt 1-mal geändert.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Definiere bitte mal Module und Scripte

Du must dir gedanken machen, wie der "Normale Benutzer" denn deine Software benutzten kann. Er soll wirklich .py Dateien schreiben, mit den Angaben, welche CD verarbeitet werden soll?!?

Dafür macht man zumindest eine CLI. (Ich würde da http://click.pocoo.org/ empfehlen)...
Aber du bist ja auch mit Tkinter unterwegs. Also dann eine GUI machen.

Aber selbst wenn er denn nun eine ".py" Datei schreiben sollte, dann könnte das so aussehen:

Code: Alles auswählen

from foo import process_cd

process_cd('Indila')
process_cd('Lindsey Sterling')
process_cd('Soha')

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@Alfons Mittelmeyer: Nochmal: Skripte sind Module also geht es in jedem Fall um Module. Die Freigabe von Speicher geschiet doch von selber, denn der Benutzer gibt keinen Speicher frei. Kann er gar nicht. Er kann nur sauber programmieren und zwar sauber im Sinne von man geht sparsam mit Namen um und teilt sein Programm sinnvoll auf Funktionen auf. Nicht mit Speicherverwaltung im Hinterkopf sondern damit das man übersichtlichen, wartbaren Quelltext erhält. Das es dann *wahrscheinlich* kein Problem mit dem Speicher gibt, ist ein netter Nebeneffekt, aber ganz sicher nicht der Hauptgrund warum man nicht zuviele Namen und zu viel Code in Funktionen ansammelt und auch nicht warum man auf Modulebene keine Variablen anlegt.

Wer ist denn jetzt der Benutzer? Von Deinem Programm? Oder von dem was Du anscheinend nur als Modul anerkennst weil das anderen angeblich kein Modul sondern ein Skript ist!? Was der Programmierer von dem Modul das am Ende ausgeführt wird tippen sollte haben wir Dir jetzt schon mehrfach gezeigt: Eine `main()`-Funktion mit einer Schleife über den variablen Teil des Codes und das ``if __name__ == '__main__':``-Idiom um die Funktion aufzurufen.

Und was Du da schon wieder mit der Standardeingabe un `eval()` und `compile()` machen willst ist absolut wirr.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Alfons Mittelmeyer hat geschrieben:Speicherverwaltung und Freigabe von Memory in Python geschehen nicht von selber, wie vorher behauptet wurde, sondern man muss entsprechend programmieren.
Das eine schließt das andere nicht aus :wink: Aber richtig müsste es heißen:

Speicherverwaltung und Freigabe von Memory in Python geschehen von selber, wenn man entsprechend programmiert.

Du kannst in jeder Sprache was falsches machen und den Speicher voll packen...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

@Alfons: eigentlich funktioniert die Welt ganz einfach: Code den du hier im Forum gezeigt hast lässt auf ein mangelndes Verständnis von Python schließen. Erfahrene Programmierer zeigen dir wie es sein sollte. Du verteidigst dein Unverständnis.
Das macht deinen Code aber nicht besser. Der - und die Problemlösung die damit abgebildet wird - bleiben Mist.
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

Ich kann zwar nichts zum Thema beitragen, aber bei
Sorry, das ist kein Modul, sondern ein Script
musste ich an "Das ist kein Tier, das ist ein Vogel" denken...
Bild
PS: Die angebotene Summe ist beachtlich.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Nochmal: Skripte sind Module also geht es in jedem Fall um Module. Die Freigabe von Speicher geschiet doch von selber, denn der Benutzer gibt keinen Speicher frei. Kann er gar nicht.
Bemühe Dich mal den Unterschied zwischen Top-Level-Script und einem Modul zu begreifen. Wenn Du einfach Python aufrufst und dann eingibst: print(5+9)
ist das dann ein Modul? Gewiss man kann auch einen File machen, etwa script.txt und den kann man dann aufrufen mit: python script.txt
Man kann auch die Fileextension .py verwenden und dann kann man das Script genauso importieren wie ein Modul. Aber vom Sinn her ist es dann immer noch kein Modul, es sei denn, dass man eine Funktion main() als library Funktion ansehen will. Wenn Du das tun willst, dann tu es. Aber ich sag dann dazu auch nichts mehr. Die Freigabe von Speicher geschieht von selber? Ein Irrglaube ist das. Der Programmierer hat dafür zu sorgen, dass die Referenzen freigegeben werden und irgendwann der Referenzzähler auf Null geht. Erst dann wird der Speicher freigegeben. Gewiß etliches davon macht Python selber, etliches aber auch nicht. Und wenn Du ordentlich programmieren willst, mußt Du wissen, was Python selber macht und was nicht. Allerdings wenn Du keine globalen Variablen verwendest, sondern nur eine Funktion oder eine Klasse nebst Instanz, dann ist der halbe Schritt schon getan und wenn Du bei tkinter nur tkinter Callbacks verwendest, dann wird es höchstwahrscheinlich schon passen. Wenn Du aber in einem Modul noch andere Referenzen verwaltest - ich hatte Message Callbacks - dann mußt Du Dich selber darum kümmern, dass diese Referenzen auch freigegeben werden.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Alfons Mittelmeyer hat geschrieben:
BlackJack hat geschrieben:@Alfons Mittelmeyer: Nochmal: Skripte sind Module also geht es in jedem Fall um Module. Die Freigabe von Speicher geschiet doch von selber, denn der Benutzer gibt keinen Speicher frei. Kann er gar nicht.
Bemühe Dich mal den Unterschied zwischen Top-Level-Script und einem Modul zu begreifen. Wenn Du einfach Python aufrufst und dann eingibst: print(5+9)
ist das dann ein Modul? Gewiss man kann auch einen File machen, etwa script.txt und den kann man dann aufrufen mit: python script.txt
Man kann auch die Fileextension .py verwenden und dann kann man das Script genauso importieren wie ein Modul. Aber vom Sinn her ist es dann immer noch kein Modul, es sei denn, dass man eine Funktion main() als library Funktion ansehen will. Wenn Du das tun willst, dann tu es. Aber ich sag dann dazu auch nichts mehr. Die Freigabe von Speicher geschieht von selber? Ein Irrglaube ist das. Der Programmierer hat dafür zu sorgen, dass die Referenzen freigegeben werden und irgendwann der Referenzzähler auf Null geht. Erst dann wird der Speicher freigegeben. Gewiß etliches davon macht Python selber, etliches aber auch nicht. Und wenn Du ordentlich programmieren willst, mußt Du wissen, was Python selber macht und was nicht. Allerdings wenn Du keine globalen Variablen verwendest, sondern nur eine Funktion oder eine Klasse nebst Instanz, dann ist der halbe Schritt schon getan und wenn Du bei tkinter nur tkinter Callbacks verwendest, dann wird es höchstwahrscheinlich schon passen. Wenn Du aber in einem Modul noch andere Referenzen verwaltest - ich hatte Message Callbacks - dann mußt Du Dich selber darum kümmern, dass diese Referenzen auch freigegeben werden. Alles was global ist, das mußt Du selber machen, also auch Referenzen aus einer modulglobalen Liste beseitigen - etwa mit pop() - oder del oder aus einem modulglobalen Dictionary.
Del allerdings hat in Verbindung mit modulglabalen Variablen nichts verloren. Denn bei Modulenn handelt es sich um Libraryfunktionen odder auch Varablen, die man in diesem Zusammenhang braucht. Und da wirft man auch nichts weg. Bei Top-Level-Scripten allerdings ist das ganz was anderes. Da kann man jederzeit neue Variablen definieren, die man nur kurzzeitig braucht, sozusagen Wegwerfvariablen für einmalige oder kurzzeitige Verwendung. Warum man sich dann gegen das Wegwerfen sträubt, geht mir allerdings nicht ein. Da sollte man sich ernsthaft darum bemühen, den Unterschied zwischen Top-Level-Scripten und Modulen zu begreifen. Ansonsten macht darüber zu reden Null Sinn.
Zuletzt geändert von Alfons Mittelmeyer am Freitag 21. August 2015, 23:09, insgesamt 1-mal geändert.
Üpsilon
User
Beiträge: 222
Registriert: Samstag 15. September 2012, 19:23

Aber vom Sinn her ist es dann immer noch kein Modul
Ja, aber der Sinn ist dem Computer egal. Du kannst es theoretisch ausführen und du kannst es theoretisch importieren. Was du praktisch machen willst, steht auf einem anderen Blatt.
PS: Die angebotene Summe ist beachtlich.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: weil Du hier noch nie Dein wahres Ziel gepostest hast, tu ich mal das für Dich. Widersprich mir, wenn ich falsch liege: Du willst eine GUI-Anwendung schreiben, wo Nutzer interaktiv Fenster gestalten können und mit Funktionen hinterlegen können. Diese Fenster können gespeichert, verschickt, ins Internet geladen werden, von dort wieder von anderen Nutzern heruntergeladen werden, bearbeitet oder benutzt werden. Also alles in einem, Editor und Ausführung von beliebig vielen "Apps".

Dazu ein paar Anmerkungen:
GUIs sind Event-gesteuert. Gerade wenn es viele Apps geben soll, ist es fast unumgänglich, eine App als Klasse zu definieren. Daher ist es schwierig, Interaktivität prozedural zu steuern, ein Skript das nacheinander Befehle ausführt widerspricht dem Grundaufbau einer GUI.
Um Fenster laden und speichern zu können, braucht es ein Datenformat, das am Besten Ähnlichkeiten zur internen Struktur hat, also eine Art Baum, wo Knöpfe und Eingabefelder die Blätter sind, die zusätzlich noch Attribute haben. Schau Dir mal ui-Dateien von QT an.
Jetzt kommen wir zum Punkt Aktionen: die hängen ja nicht in der bloßen Luft. Neben der Außenansicht (GUI) gibt es auch noch das Innenleben (Geschäftslogik) die beide erstmal nichts miteinander zu tun haben. Die Geschäftslogik sollte ohne GUI entwickelt und getestet werden, erst danach, wird sozusagen als Aufsatz eine GUI gemacht. Änderungen bedeuten dann oft eine Änderung der Datenstrukturen, und damit muß man die App komplett neustarten. Und damit komme ich zum letzten Punkt: viele Apps in einer Anwendung wird selten gemacht, weil die Nachteile überwiegen. Getrennte Prozesse sind voreinander geschützt. In Python kann so ziemlich alles dynamisch geändert werden. Eine fehlerhaft programmierte App kann damit das ganze Programm instabil machen. Und das will man normalerweise nicht haben.

Selbst so große Firmen wie Microsoft haben in ihren Visual XY den (GUI-)Editor vom Ausführen der Programme getrennt. Vielleicht gibt es den ein oder anderen Programmieranfänger, der Deine Visionen toll findet, aber damit das Projekt erfolgreich werden kann, mußt Du Dich an erprobte Praktiken halten. Dazu zählen Module, Klassen und Methoden, keine globalen Variablen, insbesondere kein eval, das globale Zustände ändert.

Das was Du bisher gezeigt hast, ist kein Python, sondern eine Art maschinennahes BASIC in Python-Syntax. Der Vorteil von Python ist, dass man sich um vieles keine Gedanken machen muß, wenn man sich an ein paar einfache Regeln hält. Bei Deiner neuen Programmiersprache muß sich der Programmierer dagegen viele Gedanken um Dinge machen, wo die meisten Programmierer froh sind, sie seit etlichen Jahren los zu sein.
Gesperrt