Was muss ich in Python 3 importieren, damit es print kennt?

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

In Python zwei hat es funktioniert, aber in Python 3 bekomme ich für die Funktion print folgende Fehlermeldung: Exception NameError: "global name 'print' is not defined"
Muss ich da etwas Bestimmtes importieren, damit python3 print kennt?
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:


GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Code: Alles auswählen

%>  python3                           
Python 3.4.3+ (default, Jul 28 2015, 13:17:50) 
[GCC 4.9.3] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print("hallo alfons")
hallo alfons
Es gab zwar Aenderungen an `print` zwischen Python2 und Python3, aber einen NameError bekommt ich nur auf eine Weise hin:

Code: Alles auswählen

>>> del print
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'print' is not defined
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Danke, jetzt habe ich es nochmals ausprobiert. Print alleine geht schon. Aber in der Form geht es nicht:

Code: Alles auswählen

class myprint(object):
    def __del__(self):
        print('Destroyed')

todestroy = myprint()
Und es geht dann nicht, wenn ich den Namespace lösche, dann kennt Python3 print nicht mehr. Muss man den Namespace vielleicht in einer bestimmten Reihenfolge löschen? Ich meine wenn man etwa __builtin__ löscht bevor man todestroy löscht, dann könnte es vielleicht Probleme geben. Oder was könnt Ihr mir dazu sagen?

Ich glaube ich weiss jetzt, wie ich es richtig machen muss. Dauert nur ein wenig.
BlackJack

@Alfons Mittelmeyer: Lass die Finger von der `__del__()`-Methode. Die ist *nicht* nützlich für Dich. Falls man die tatsächlich mal braucht, dann sollte man genau wissen wie die Speicherverwaltung mit dieser Methode zusammenarbeitet, unter anderem auch welche Garantien einem Python bietet welche Objekte und Namensräume zum Zeitpunkt des Aufrufs zur Verfügung stehen und welche bereits weg sein können. Also zum Beispiel hätte Dich das jetzt nicht überraschen dürfen das eine Funktion wie `print()` nicht mehr existieren muss wenn `__del__()` aufgerufen wird. Du hast mehrfach demonstriert das Du hier keine Ahnung hast und auch nicht haben willst.

Bitte fang jetzt nicht wieder eine Diskussion mit Argumenten an die Du anderswo schon gebracht hast. Ich schaue mir diese sinnlosen Wiederholungen nicht lange an. Die bringen keinen weiter, kosten unnötig Zeit, und Du vermittelst neuen Lesern falsche, wirklich *falsche* Vorstellungen davon wie Speicherverwaltung in Python zu handhaben ist.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Lass die Finger von der `__del__()`-Methode. Die ist *nicht* nützlich für Dich. Falls man die tatsächlich mal braucht, dann sollte man genau wissen wie die Speicherverwaltung mit dieser Methode zusammenarbeitet, unter anderem auch welche Garantien einem Python bietet welche Objekte und Namensräume zum Zeitpunkt des Aufrufs zur Verfügung stehen und welche bereits weg sein können. Also zum Beispiel hätte Dich das jetzt nicht überraschen dürfen das eine Funktion wie `print()` nicht mehr existieren muss wenn `__del__()` aufgerufen wird. Du hast mehrfach demonstriert das Du hier keine Ahnung hast und auch nicht haben willst.

Bitte fang jetzt nicht wieder eine Diskussion mit Argumenten an die Du anderswo schon gebracht hast. Ich schaue mir diese sinnlosen Wiederholungen nicht lange an. Die bringen keinen weiter, kosten unnötig Zeit, und Du vermittelst neuen Lesern falsche, wirklich *falsche* Vorstellungen davon wie Speicherverwaltung in Python zu handhaben ist.
Sorry Ich lasse die Finger weg von del. Siehst Du doch. Jetzt auch geschafft für Python3:

foo.py:

Code: Alles auswählen

class Foo(object):
    def __del__(self):
        print('Collected')

f = Foo()
Modul collect.py:

Code: Alles auswählen

import gc
from copy import copy

def destroy(a):
    c = copy(a)
    for k,e in c.items():
        if k != '__builtins__': a.pop(k)

def start():
    for _ in range(10):
        a = {}
        eval(compile(open('foo.py', "rb").read(), 'foo.py', 'exec'), a)
        destroy(a)
        print(gc.collect(), len(gc.garbage))
Und dann aufrufen mit:

Code: Alles auswählen

python3
import collect
collect.start()
Und kein del benutzt. Alles richtig gemacht oder? pop() wird man ja noch nehmen dürfen, oder auch verboten?
BlackJack

@Alfons Mittelmeyer: Nein, nicht alles richtig gemacht, sondern alles falsch, weil Du immer noch versuchst Probleme zu lösen die es nicht gibt.

Die `destroy()`-Funktion ist sinnlos, da sie nach aussen keinen Effekt hat.

In diesem Fall würde ich sagen das `pop()` ”verboten” ist, denn das ist nicht der offensichtliche Weg ein Schlüssel/Wert-Paar aus einem Wörterbuch zu entfernen. Wenn der Rückgabewert von `pop()` nicht verwendet wird, dann ist das semantisch der falsche Weg. Dafür gibt es nämlich ``del``. Da Du aber immer noch versuchst Speicher manuell zu verwalten, wie man an den Aufrufen von `gc`-Funktionen sieht, ist der Code unsinnig. Und mit dieser Speicherverwaltungsgeschichte nähert sich dieses Thema auch schnell dem gesperrt-werden.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Nein, nicht alles richtig gemacht, sondern alles falsch, weil Du immer noch versuchst Probleme zu lösen die es nicht gibt.

Die `destroy()`-Funktion ist sinnlos, da sie nach aussen keinen Effekt hat.

In diesem Fall würde ich sagen das `pop()` ”verboten” ist, denn das ist nicht der offensichtliche Weg ein Schlüssel/Wert-Paar aus einem Wörterbuch zu entfernen. Wenn der Rückgabewert von `pop()` nicht verwendet wird, dann ist das semantisch der falsche Weg. Dafür gibt es nämlich ``del``. Da Du aber immer noch versuchst Speicher manuell zu verwalten, wie man an den Aufrufen von `gc`-Funktionen sieht, ist der Code unsinnig. Und mit dieser Speicherverwaltungsgeschichte nähert sich dieses Thema auch schnell dem gesperrt-werden.
Das Thema ist zuende, denn es ist vollbracht!

Aber das verstehe ich wirklich nicht. Zuerst schreibst Du immer dass man del nicht benutzen darf, jetzt aber, dass ich es benutzen hätte sollen. Wer soll daraus noch schlau werden?

Und nach außen keinen Effekt soll die destroy Funktion haben? Sie löscht nur alles raus, was im Namespace ist. Viel besser als del für eine Funktion. Jetzt nämlich gleich alles und ganz ohne del.
BlackJack

@Alfons Mittelmeyer: Man soll ``del`` nicht benutzen um manuell Speicher verwalten zu wollen, ganz einfach weil das nicht funktioniert. Zum löschen von Namen weil man einen Namen aus einem Namensraum weg haben möchte, oder beispielsweise zum entfernen eines Schlüssel/Wert-Paares aus einem Wörterbuch, kann man es natürlich verwenden, weil es *dafür* ja auch *vorgesehen* ist.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Man soll ``del`` nicht benutzen um manuell Speicher verwalten zu wollen, ganz einfach weil das nicht funktioniert. Zum löschen von Namen weil man einen Namen aus einem Namensraum weg haben möchte, oder beispielsweise zum entfernen eines Schlüssel/Wert-Paares aus einem Wörterbuch, kann man es natürlich verwenden, weil es *dafür* ja auch *vorgesehen* ist.
Aber das ist ja dasselbe. Die Schlüsselwertpaare sind ja die globalen Variablen, Funktionen und Objekte. Und wenn ich jetzt del gemacht hätte, dann wäre es ja das Gleiche gewesen, was Ihr vorher so kritisiert hattet.

Also Sinn ergibt das keinen. Wenn man Funktionen mit del löscht, ist es verboten. Wenn man sie aber über ein Dictionary mit del löscht, dannn darf man das wieder.
BlackJack

@Alfons Mittelmeyer: Wenn Du versuchst mit ``del`` auf einem Wörterbuch *Speicherverwaltung* zu betreiben, dann ist es natürlich ”verboten”. Es verbietet sich von selbst weil das nicht funktioniert. Nur Du willst das einfach nicht wahrhaben. Weshalb das hier echt nervt. Und die `destroy()`-Funktion zeigt wieder mal das Du nicht weisst was Du da tust. Da ist es egal ob man `pop()` oder ``del`` verwendet, weil die wirklich absolut sinnfrei ist und *nichts* bewirkt ausser Rechenzeit zu verwenden.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: hättest Du verstanden, von was wir hier die ganze Zeit reden, wärst Du gar nicht auf die Idee gekommen, del durch pop zu ersetzen, das ist so als ob Du blaue Smarties durch braune Smarties ersetzt. Noch skurriler finde ich ja das copy. Du willst hier manuelle Speicherverwaltung machen, verhinderst diese aber dadurch, dass Du eine Kopie machst.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: hättest Du verstanden, von was wir hier die ganze Zeit reden, wärst Du gar nicht auf die Idee gekommen, del durch pop zu ersetzen, das ist so als ob Du blaue Smarties durch braune Smarties ersetzt. Noch skurriler finde ich ja das copy. Du willst hier manuelle Speicherverwaltung machen, verhinderst diese aber dadurch, dass Du eine Kopie machst.
Die Kopie ist lokal definiert und wird daher bei Ende der Funktion automatisch beseitigt. Und diese Kopie wird benötigt, damit ich aus dem Originaldictionary rauslöschen kann. Solange ich in einer Schleife über ein Dictionary bin, darf ich nämlich aus dem Dictionary nichts löschen. Daher die Kopie.

Und von Speicherverwaltung habt Ihr anscheinend Null Ahnung. Es gibt Programme an denen hunderte von Programmierer arbeiten, die einige Millionen Zeilen von Quellcode haben und da sind die Prinzipien korrekter Speicherverwaltung genau zu beachten. Und wenn Ihr da arbeiten würdet und auf Euren skurrilen Ansichten über Speicher freigeben beharren würdet, bliebe nichts übrig als Euch gleich wieder rauszuwerfen.

Was soll denn dieser Unsinn wieder: wenn man große Datenmengen als Eintrag in eine Liste abspeichert oder in ein Dictionaty, darf man diesen Eintrag wieder löschen, sogar mit Del. Wenn man dafür aber eine Variable dynamisch anlegt, dann darf man die nicht wieder löschen, sondern muß sie im Speicher behalten, weil man hier kein Del benutzen darf? Und wenn dann andere Module auch viel Speicher brauchen, dann eben Crash. Es ist die Pflicht jedes professionellen Programmierers, dynamisch belegten Speicher wieder freizugeben und normalerweise nimmt man den dafür vorgesehenen Befehl, der in C++ etwa free heißt und bei Python del. Für Pipifax Desktop Anwendungen freilich, braucht man so etwas nicht.

Und Ihr wollt mir vorschreiben, dass hier schlampig programmieren Pflicht ist und korrekt programmieren verboten?

Oder muß man statt del Neuzuweisung nehmen?

Code: Alles auswählen

def function():
    xxxx
    xxxx

function()
function = None
Hier behält man zwar die Variable, die in diesem Fall eine Funktion war in anderen Fällen eine Variable mit grossen Datenmengen sein könnte, minimiert aber zumindest den Speicher.

Im Prinzip ist so eine Neuzuweisung dasselbe wie etwa in C++:

Code: Alles auswählen

# das soll verboten sein, weil man es nicht benutzen darf?
free Variable

#das allerdings ist erlaubt, weil man da free nicht benutzt hat? Bei C++ muss man diese Zuweisung allerdings  in zwei Zeilen schreiben:
free Variable
Variable = None
Also pop und Zuweisung enthalten das del implizit. Man braucht es daher nicht extra schreiben. Und Neuzuweisung wäre genauso eine Lösung, wenn man beim nächstenmal den Namen wiederwenden sowieso wiederwenden will. Wenn man ihn aber nicht mehr wiederverwenden will, dann ist eine Neuzuweisung keine Lösung. Die andere Lösung wäre statt Namen indizes auf Listen zu verwenden oder Einträge in Diichtionaries. Aber ich möchte ungern so programmieren:

Code: Alles auswählen

VAR['myfunction'](par1, par2, par3)
del VAR['myfunction']

Die destroy Funktion habe ich jetzt verbessert, denn man braucht kein deep copy und darf anscheinen hier schon del nehmen:
[Code=python file=Untitled.py]def destroy(a):
    c = dict(a)
    for k,e in c.items():
        if k != '__builtins__': del a[k]
Einfach nur clear() nehmen funktionierte zufällig bei python2. Wenn man aber einfach nur clear() nimmt, ist die Löschreihenfolge zufällig. Und wenn dann '__builtins__' zuerst gelöscht wird, sind danach Funktionen wie print() unbekannt und wenn man __del()__ Methoden mit Funktionen wie print drin hat, bekommt man dann Fehlermeldungen.
Zuletzt geändert von Alfons Mittelmeyer am Sonntag 16. August 2015, 10:57, insgesamt 1-mal geändert.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Du willst halt auf biegen und brechen den Speicher selbst verwalten.
Somit sind alle sprachen die das nicht ermöglichen, weil sie es automatisch machen, nichts für dich.

Also, entweder du hörst damit auf, oder du must eine andere Sprache nehmen.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jens hat geschrieben:Du willst halt auf biegen und brechen den Speicher selbst verwalten.
Somit sind alle sprachen die das nicht ermöglichen, weil sie es automatisch machen, nichts für dich.

Also, entweder du hörst damit auf, oder du must eine andere Sprache nehmen.
Jede Sprache verwaltet den Speicher automatisch. So werden lokale Variablen wieder gelöscht. Globale Variablen werden aber nicht gelöscht. Das muß man in jeder Programmiersprache selber machen. Python macht das genauso wenig. Und wenn man große Datenmengen in einem Modul lädt, die man nur temporär braucht und im Speicher läßt, und das bei noch anderen Modulen genauso macht, dann crasht das Programm bald. Lade einfach mal movies, etwa Spielfilme, mit verschiedenen Modulen und lass sie drinnen.

Weiß nicht ob marhal.load so etwas macht. Dass man damit etwa eine Movie von zwei Gigabyte in eine Variable laden kann, und ob die Variablen in Python so gross sein dürfen. Jedenfalls wenn man das ein paarmal hintereinander machen würde und jedesmal eine neue Variable benützt, ohne die vorige zu löschen.: lang macht man das jedenfalls nicht.
Zuletzt geändert von Alfons Mittelmeyer am Sonntag 16. August 2015, 11:36, insgesamt 2-mal geändert.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das ist Unsinn :roll:

Schau dir mal https://de.wikipedia.org/wiki/Garbage_Collection an!

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Alfons Mittelmeyer hat geschrieben:Euren skurrilen Ansichten
Euch gleich wieder rauszuwerfen
Was soll denn dieser Unsinn wieder
Es ist die Pflicht jedes professionellen Programmierers
Für Pipifax Desktop Anwendungen freilich, braucht man so etwas nicht
Und Ihr wollt mir vorschreiben, dass hier schlampig programmieren Pflicht ist und korrekt programmieren verboten?
Geh bitte. Du bist hier anscheinend falsch. ><((((*>
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Also beachtet bitte die Regel: del darf man für Einträge in dictionaries nehmen und für Einträge in Listen, sonst aber nicht.
Die richtige Art globale einzelne Definitionen zu löschen - also was man nicht in globale Listen oder globale Dictionaries eingetragen hat - ist daher diese:

Code: Alles auswählen

def myfunction(): pass

del globals()['myfunction']
globals() ist allerdings nur der Namensraum für die Hauptanwendung.
Zuletzt geändert von Alfons Mittelmeyer am Sonntag 16. August 2015, 12:08, insgesamt 1-mal geändert.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Alfons Mittelmeyer hat geschrieben:Jede Sprache verwaltet den Speicher automatisch. So werden lokale Variablen wieder gelöscht. Globale Variablen werden aber nicht gelöscht.
Du vermischt da einige Konzepte. In kompelierten Sprachen werden globale Variablen üblicherweise im `.data`-Segement abgelegt:

Code: Alles auswählen

int x = 3;
static int y = 5;

void main(void) {}

Code: Alles auswählen

╭─dav1d@doom  /tmp  
╰─$ gcc global.c -o global 
╭─dav1d@doom  /tmp  
╰─$ objdump -t global

global:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*	0000000000000000              init.c
0000000000000000 l    df *ABS*	0000000000000000              crtstuff.c
0000000000401928 l     O .jcr	0000000000000000              __JCR_LIST__
0000000000401930 l     O .tm_clone_table	0000000000000000              __TMC_LIST__
0000000000400490 l     F .text	0000000000000000              deregister_tm_clones
00000000004004d0 l     F .text	0000000000000000              register_tm_clones
0000000000400510 l     F .text	0000000000000000              __do_global_dtors_aux
0000000000401940 l     O .bss	0000000000000001              completed.6938
0000000000401930 l     O .fini_array	0000000000000000              __do_global_dtors_aux_fini_array_entry
0000000000400530 l     F .text	0000000000000000              frame_dummy
0000000000401938 l     O .init_array	0000000000000000              __frame_dummy_init_array_entry
0000000000000000 l    df *ABS*	0000000000000000              global.c
0000000000401924 l     O .data	0000000000000004              y
0000000000000000 l    df *ABS*	0000000000000000              crtstuff.c
00000000004006d8 l     O .eh_frame	0000000000000000              __FRAME_END__
0000000000401928 l     O .jcr	0000000000000000              __JCR_END__
0000000000401918 l     O .data	0000000000000000              .hidden __dso_handle
0000000000401930 l     O .tm_clone_table	0000000000000000              .hidden __TMC_END__
0000000000401710 l     O .dynamic	00000000000001d0              .hidden _DYNAMIC
0000000000401938 l       .init_array	0000000000000000              .hidden __init_array_start
0000000000401940 l       .init_array	0000000000000000              .hidden __init_array_end
00000000004018e8 l     O .got.plt	0000000000000028              .hidden _GLOBAL_OFFSET_TABLE_
00000000004005d0 g     F .text	0000000000000002              __libc_csu_fini
0000000000400460 g     F .text	000000000000002a              _start
0000000000400560 g     F .text	0000000000000065              __libc_csu_init
0000000000400556 g     F .text	0000000000000007              main
0000000000401910  w      .data	0000000000000000              data_start
00000000004005e0 g     O .rodata	0000000000000004              _IO_stdin_used
0000000000000000       F *UND*	0000000000000000              __libc_start_main
0000000000401910 g       .data	0000000000000000              __data_start
0000000000000000  w      *UND*	0000000000000000              __gmon_start__
0000000000400408 g     F .init	0000000000000000              _init
00000000004005d4 g     F .fini	0000000000000000              _fini
0000000000000000  w      *UND*	0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000  w      *UND*	0000000000000000              _ITM_registerTMCloneTable
0000000000000000  w      *UND*	0000000000000000              _Jv_RegisterClasses
0000000000401920 g     O .data	0000000000000004              x
0000000000401940 g       *ABS*	0000000000000000              _edata
0000000000401940 g       *ABS*	0000000000000000              __bss_start
0000000000401941 g       *ABS*	0000000000000000              _end
Darin findet man diese 2 Einträge:

Code: Alles auswählen

0000000000401924 l     O .data	0000000000000004              y
0000000000401920 g     O .data	0000000000000004              x
Also globale Variablen haben schonmal absolut nichts mit Speicherverwaltung zu tun (PS: ob die globale Variable mit static deklariert wurde oder nicht sieht man am `l` oder `g`).

Nun zu lokalen Variablen, diese werden auf einem Stack-Segement abgelegt, welches von dem Stack wieder "entfernt" wird sobald die der Scope verlassen wird.

Nun zur eigenltichen Speicherverwaltung, dem Heap, das "Gegenstück" zum Stack, welcher nicht automatisch wächst und Speicher nicht "automatisch" freigegeben werden wie beim Stack. Speicher der im Heap reserviert wird bleibt bestehen bis er wieder freigegeben wird. Man kann z.B. Speicher via `malloc` reservieren und wieder mit `free` freigeben, dann gibt es noch die Variante über einen Garbage Collector (von Jens angesprochen) Speicher zu reservieren, der GC kümmert sich darum dass Speicher wieder freigegeben wird sobald er nicht mehr benutzt wird (vereinfacht: er scannt den Speicherbereich nach Referenzen/Pointern, wenn er etwas findet dass in einen reservierten Bereich zeigt, wird der Speicher noch gebraucht und nicht freigegeben).

Python benutzt einen solchen Garbage Collector (gibts übrigens auch für C/C++, z.B. libgc). Also alles was du tust ist im Grunde dem Garbage Collector die Arbeit zu erschweren und machst es teilweise sogar schlimmer (z.B. das copy). Es kann durchaus Situationen geben in denen `del` Sinn macht, allerdings für jemanden wie dich, der nicht wirklich versteht was los ist mit Memory Management sollte die Finger davon lassen.

Fazit: Du verrennst dich da in Sinnlosem, wenn du wirklich ein low memory profile brauchst (also wirklich wirklich wirklich low), dann nimm nicht Python. Aber denke jetzt nicht, wusste ich doch gleich Python taugt nix, Garbage Collectoren sind scheiße. Python läuft ohne Probleme auf Micro-Controllern und ein guter Garbage Collector kann durchaus mal schneller und effizienter sein als manuelles Memory Management von einem der keine Ahnung hat wies geht ;).

PS: Wenn du versuchst Module zu entladen, das geht sowieso nicht wirklich: http://bugs.python.org/issue9072.
the more they change the more they stay the same
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Dav1d hat geschrieben:
Alfons Mittelmeyer hat geschrieben:Jede Sprache verwaltet den Speicher automatisch. So werden lokale Variablen wieder gelöscht. Globale Variablen werden aber nicht gelöscht.
Du vermischt da einige Konzepte. In kompelierten Sprachen werden globale Variablen üblicherweise im `.data`-Segement abgelegt:
Du vermischt da einige Konzepte. Statische globale Variablen werden im '.data' - Segment abgelegt. Bei dynamisch allokiertem Speicher werden nur die Pointer also die Verweise auf den Speicher im '.data' Segment abgelegt. Und der Speicher wird dann aus dem Heap allokiert, etwa:

Code: Alles auswählen

# hier wird ein globaler Pointer myVar definiert, der im '.data' Segment als Verweis auf bisher nichts Brauchbares abgelegt wird.
# außerdem wird er als Pointer auf eine Klasse definiert, sodass er nur auf diese Klasse anwendbar ist
# (natürlich gibt es auch Möglichkeiten Pointer für beliebige Klassen zu verwenden mit Datentyp void und dann type casts)
MyClass * myVar = Null

# und hier findet dann die eigentliche Zuweisung statt, in der dann Speicher dynamisch allokiert wird
myVar = new MyClass(par1,par2,par3)

# und wenn der Speicher nicht freigegeben wird, bleibt dieser erhalten. Genauso ist es in Python. Zum Freigeben existiert der Befehl delete und in Python heißt er del
# Python hat allerdings eine Speicherverwaltung, die sich um Vieles kümmert, sodass man das del nicht explizit braucht, weil es in einigen Befehlen schon enthalten ist.
# wenn man in C++ nun das schreiben würde, wäre es verkehrt:
myVar = new MyClass(otherpar1,otherpar2,otherpar3)

# denn dadurch verursacht man ein Memory Leak, weil man jetzt neuen Speicher allokiert hat, ohne den alten freizugeben
# richtig daher:
delete myVar
myVar = new MyClass(otherpar1,otherpar2,otherpar3)

# In Python ist hier ein del völlig unnötig, wel das del bereits in der Zuweisung mit enthalten ist, genauso, wie etwa auch bei pop()
# Und wer hier del benutzt betreibt Mikroprogrammierung und hat von der Speicherverwaltung von Python nichts verstanden
Dav1d hat geschrieben:Also globale Variablen haben schonmal absolut nichts mit Speicherverwaltung zu tun (PS: ob die globale Variable mit static deklariert wurde oder nicht sieht man am `l` oder `g`).
Wie wir gesehen hatten, haben globale Pointer mit dynamisch allokiertem Speicher sehr wohl etwas mit Speicherverwaltung zu tun. Bei statischen Variablen bleibt allerdings der Speicher stets gleich und muss man sich nicht darum kümmern. Der Vorteil der Speicherverwaltung von Python ist, dass man sich normalerweise durch das in der Zuweisung und der pop-Funktion bereits enthaltene del, so ziemlich gar nicht um die Speicherverwaltung zu kümmern braucht. Stimmt natürlich nicht ganz, denn wer Daten in Listen und dergleichen speichert, da immer mehr hineinmüllt und sich nicht darum kümmert, dass etwas nur kurzzeitig gebraucht wurde, und glaubt, dass die Speicherverwaltung automatisch seinen Saustall aufräumt, der liegt verkehrt.
Dav1d hat geschrieben:Nun zur eigenltichen Speicherverwaltung, dem Heap, das "Gegenstück" zum Stack, welcher nicht automatisch wächst und Speicher nicht "automatisch" freigegeben werden wie beim Stack. Speicher der im Heap reserviert wird bleibt bestehen bis er wieder freigegeben wird. Man kann z.B. Speicher via `malloc` reservieren und wieder mit `free` freigeben, dann gibt es noch die Variante über einen Garbage Collector (von Jens angesprochen) Speicher zu reservieren, der GC kümmert sich darum dass Speicher wieder freigegeben wird sobald er nicht mehr benutzt wird (vereinfacht: er scannt den Speicherbereich nach Referenzen/Pointern, wenn er etwas findet dass in einen reservierten Bereich zeigt, wird der Speicher noch gebraucht und nicht freigegeben).


Daraus besonders dieser Teil:
der GC kümmert sich darum dass Speicher wieder freigegeben wird sobald er nicht mehr benutzt wird[/b] (vereinfacht: er scannt den Speicherbereich nach Referenzen/Pointern, wenn er etwas findet dass in einen reservierten Bereich zeigt, wird der Speicher noch gebraucht und nicht freigegeben).
Ob der Speicher noch benutzt werden soll, weiss der gc nicht. Er weiss nur ob der Referenzzähler Null ist oder nicht - bzw. ob die Referenz noch beinen reservierten Speicherbereich zeigt. Also, ob etwas noch gebraucht wird, weiß der gc nicht und wenn jemand Objekte, die er nicht mehr braucht, nicht aufräumen will sondern einfach weiter ansammelt, dann wird eben der Speicher vollgemüllt, bis Python bedendet wird oder bis es einen Crash gibt. Und bei lang laufenden Programmen mit großen Datenbeständen, kommt es eben dann zu Crashs.

Während lokale Variablen in Funktionen selber wieder beseitigt werden, werden globale Variablen nicht von selber aufgeräumt, sondern die Daten bleiben erhalten, bis man sie löscht. Warum man bei Einträgen in Listen und Directories dazu del nehmen darf, bei einzelnen Variablen dagegen nicht, bleibt ein Rätsel.
Dav1d hat geschrieben:Python benutzt einen solchen Garbage Collector (gibts übrigens auch für C/C++, z.B. libgc). Also alles was du tust ist im Grunde dem Garbage Collector die Arbeit zu erschweren und machst es teilweise sogar schlimmer (z.B. das copy). Es kann durchaus Situationen geben in denen `del` Sinn macht, allerdings für jemanden wie dich, der nicht wirklich versteht was los ist mit Memory Management sollte die Finger davon lassen.
Anscheinend bin ich der einzige hier der etwas vom Memory Management versteht. Und solche wie Du sollten da einfach besser still sein. Vielleicht viel Bücher gelesen, verstanden aber offentlich nichts.
Dav1d hat geschrieben:Fazit: Du verrennst dich da in Sinnlosem, wenn du wirklich ein low memory profile brauchst (also wirklich wirklich wirklich low), dann nimm nicht Python. Aber denke jetzt nicht, wusste ich doch gleich Python taugt nix, Garbage Collectoren sind scheiße. Python läuft ohne Probleme auf Micro-Controllern und ein guter Garbage Collector kann durchaus mal schneller und effizienter sein als manuelles Memory Management von einem der keine Ahnung hat wies geht ;).

PS: Wenn du versuchst Module zu entladen, das geht sowieso nicht wirklich: http://bugs.python.org/issue9072.
Ich brauche kein low memory profile aber ein grow and grow and grow memory profile ebensowenig. Und Python ist optimal geeignet, hervorragend. Ein guter Garbage Collector kann keinen Saustall aufräumen, weil jemand den Speicher vollmüllt. Ein manuelles Memory Management brauche ich nicht. Denn ich habe die destroy() Funktion geschrieben, die den Speicher leer räumt. Und wer überhaupt keine Ahnung hat, bist Du. Sonst hättest Du gemerkt, dass ich darüber gar nicht mehr dikutieren brauche, weil ich die Funktion habe, die automatisch nach Ablaufen eines Scripts, den vom Script verwendeten Speicher wieder löscht. Und um Module ging es auch nicht, sondern um Scripts.
Gesperrt