Performance-Unterschied zw.: import x / from x import y

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
Benutzeravatar
HorstJENS
User
Beiträge: 123
Registriert: Donnerstag 9. Februar 2006, 21:41
Wohnort: Wien, Österreich
Kontaktdaten:

Samstag 10. Juni 2006, 07:06

Hallo, hier eine Anfaengerfrage:
macht es einen Unterschied fuer die Performance (Speicherverbrauch, Geschwindigkeit) wenn ich ein komplettes Modul importiere oder nur eine einzige Funktion aus diesem Modul ?
z,B.:
hat

Code: Alles auswählen

import random
Nachteile gegenüber

Code: Alles auswählen

from random import randint
?
(Angenommen ich brauch vom Modul random wirklich nur die Funktion randint)
http://spielend-programmieren.at
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Samstag 10. Juni 2006, 11:27

import random ist wirklich langsamer.
er verbraucht dann weinger speicher.
solange es sich um ein kleines modul handelt, kein problem,
erst bei großen und/oder vielen modulen hat das eine klare beeinträchtigung.
wie viel dabei verlorengeht an geschwindigkeit, kannste ja über time herausfinden!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Samstag 10. Juni 2006, 16:27

murph hat geschrieben:import random ist wirklich langsamer.
er verbraucht dann weinger speicher.
Hi murph!

Woher weißt du das? Hast du irgendwelche Zahlen für uns? Einen Benchmark? Oder ist das nur Gefühl?

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
HorstJENS
User
Beiträge: 123
Registriert: Donnerstag 9. Februar 2006, 21:41
Wohnort: Wien, Österreich
Kontaktdaten:

Samstag 10. Juni 2006, 17:16

murph hat geschrieben:import random ist wirklich langsamer.
er verbraucht dann weinger speicher.
solange es sich um ein kleines modul handelt, kein problem,
erst bei großen und/oder vielen modulen hat das eine klare beeinträchtigung.
wie viel dabei verlorengeht an geschwindigkeit, kannste ja über time herausfinden!
Du meinst

Code: Alles auswählen

import random
verbraucht WENIGER Speicher als

Code: Alles auswählen

from random import randint
?
Ich hätte es genau umgekehrt vermutet...

Habe versucht mittels time-Funktion herauszufinden ob es einen Unterschied macht, habe aber bei beiden Methoden das gleiche Ergebnis bekommen. Da mein Testprogramm wahrscheinlich zu klein und ungenau war für eine genaue Messung hab ich mir gedacht ich frage die Profis hier im Forum.
http://spielend-programmieren.at
Benutzeravatar
SigMA
User
Beiträge: 181
Registriert: Sonntag 4. April 2004, 13:27
Wohnort: Freiburg
Kontaktdaten:

Samstag 10. Juni 2006, 19:36

Code: Alles auswählen

import random
Ist schonender für den Interpreter, da er dann nur schaut was wirklich benötigt wird.
Weiß man dies eh schon genau kann man gedrost zu

Code: Alles auswählen

from random import randint
nehmen

SigMA
Leichtdio.de - Das Kreativ-Blog
http://www.leichtdio.de
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Samstag 10. Juni 2006, 19:49

Hi!

Ich **vermute** -- das heißt, ich weiß es nicht --, dass in beiden Fällen das Modul komplett gelesen, also in den Speicher geladen wird. Zusätzlich werden **wahrscheinlich** auch alle Module in den Speicher geladen, die in oberster Ebene des zu importierenden Moduls importiert werden. Also alle Module, die nicht in den Funktionen importiert werden.

Was für mich bedeutet, dass es **vermutlich** kaum einen Unterschied geben wird.

Eine meiner Messungen -- das ist schon eine Weile her -- hat ergeben, dass das Modul nur beim ersten Imporieren in den Speicher geladen wird. Egal wie oft man das Modul in anderen Funktionen oder in nachträglich importierten Modulen läd, es wird kein zusätzlicher Speicher mehr für das bereits importierte Modul verbraucht.

Wahrscheinlich wird geprüft, ob das Modul bereits geladen ist und es wird nur noch für den Bereich (global, lokal), in dem das Modul noch einmal importiert wird, der Namensbereich des Moduls zur Verfügung gestellt.

Allerdings sollte man es vermeiden, ein Modul in einer Funktion zu importieren, die oft aufgerufen wird. So gering auch der Aufwand, des Prüfens ob das Modul bereits geladen ist, scheint -- es ist ein Mehraufwand den man merkt.

Aber auf die Frage, ob from foo import bar schneller ist als import foo, habe ich leider keine wirkliche Antwort. Allerdings ist es mir auch egal. :roll:

Falls jemand fragt: Nein, die Tests habe ich nicht mehr.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Samstag 10. Juni 2006, 19:55

Das war damals der Auslöser für meine Tests:
http://www.python-forum.de/post-9538.html#9538

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
SigMA
User
Beiträge: 181
Registriert: Sonntag 4. April 2004, 13:27
Wohnort: Freiburg
Kontaktdaten:

Samstag 10. Juni 2006, 20:04

gerold hat geschrieben:Wahrscheinlich wird geprüft, ob das Modul bereits geladen ist und es wird nur noch für den Bereich (global, lokal), in dem das Modul noch einmal importiert wird, der Namensbereich des Moduls zur Verfügung gestellt.
python.org hat geschrieben:Although Python's interpreter is optimized to not import the same module multiple times, repeatedly executing an import statement can seriously affect performance in some circumstances.
gerold hat geschrieben:Allerdings sollte man es vermeiden, ein Modul in einer Funktion zu importieren, die oft aufgerufen wird. So gering auch der Aufwand, des Prüfens ob das Modul bereits geladen ist, scheint -- es ist ein Mehraufwand den man merkt.
python.org hat geschrieben:def doit1():

Code: Alles auswählen

import string             ###### import statement inside function
    string.lower('Python')

for num in range(100000):
    doit1()
or:

Code: Alles auswählen

import string             ###### import statement outside function
def doit2():
    string.lower('Python')

for num in range(100000):
    doit2()
doit2 will run much faster than doit1, even though the reference to the string module is global in doit2.
Leichtdio.de - Das Kreativ-Blog
http://www.leichtdio.de
murph
User
Beiträge: 622
Registriert: Freitag 14. April 2006, 19:23
Kontaktdaten:

Samstag 10. Juni 2006, 20:56

sorry, meinte es anders als verstanden. heir überarbeitet:
import random ist wirklich langsamer.
er verbraucht dann ,wenn er from x import y macht,weinger speicher.
solange es sich um ein kleines modul handelt, kein problem,
erst bei großen und/oder vielen modulen hat das eine klare beeinträchtigung.
wie viel dabei verlorengeht an geschwindigkeit, kannste ja über time herausfinden!
BlackJack

Samstag 10. Juni 2006, 20:59

HorstJENS hat geschrieben:macht es einen Unterschied fuer die Performance (Speicherverbrauch, Geschwindigkeit) wenn ich ein komplettes Modul importiere oder nur eine einzige Funktion aus diesem Modul ?
z,B.:
hat

Code: Alles auswählen

import random
Nachteile gegenüber

Code: Alles auswählen

from random import randint
?
(Angenommen ich brauch vom Modul random wirklich nur die Funktion randint)
Das Modul wird in jedem Fall komplett geladen und ausgeführt wenn man es das erste mal importiert. Dabei ist es völlig egal wie gross das Modul ist. Bei der zweiten Form werden dann noch die entsprechenden Objekte im importierenden Modul an lokale Namen gebunden.

Wenn das auf Modulebene passiert, dann wird das nur einmal gemacht. Wenn man innerhalb einer Funktion/Methode importiert, dann wird beim ersten Aufruf das Modul importiert und ausgeführt und bei jedem weiteren Aufruf wird nur getestet und festgestellt, das das Modul schon importiert wurde.

Ich mache ``import``\s fast immer auf Modul-Ebene oben im Modul, damit ich auf einen Blick die Abhängigkeiten sehen kann und nicht erst den ganzen Quelltext absuchen muss.
Antworten