Wie initialisiere ich Dateien und SQL DB in Modulen richtig?

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
Herr Lehmann
User
Beiträge: 81
Registriert: Samstag 14. August 2010, 22:20

Hallo!



Ich habe ein Programm mit mehreren eigenen Modulen z.b.

main

Code: Alles auswählen

import unter1
import threading



name = "Otto"
tier = "Elefant"
unter1.prog1(name,tier)


th1=threading.Thread(target=unter1.prog2)
th2=threading.Thread(target=unter1.prog3)
th3=threading.Thread(target=unter1.prog4)

th1.start()
th2.start()
th3.start()

und modul unter1:

Code: Alles auswählen

import sqllite3


conn = sqlite3.connect('data.sql')
c = conn.cursor()
obj = open("test.txt", "r")


def prog1(name,tier):
	for name in obj:
		print "Test"
		#do something
	
def prog2():
	c.execute('SELECT * FROM data LIMIT 1')
    result = c.fetchone()[0]
    
    return result



def prog3():
	while True:
		print "BlaBlub"
		
def prog4():
	while True:
		print "Biba"




Was ich haben möchte ist, dass alle Dateien und Datebenbank Connections schon beim Import des Moduls geschehen, da das Programm zur Laufzeit möglichst schnell sein soll. Die Connection zu der Datenbank klappt nur wenn ich kein Threading einsetze, sonst bekomme ich einen Error das Sqllite in dem einen Thread gestartet wurde aber in einem anderen ausgeführt wird. Ist mir auch klar. Die Datei test.txt in unter1 wird leider gar nicht geöffnet. Wenn ich die Methode prog1 aufrufen würde bekäme ich einen I/O Error.

Meine Frage dazu ist, wie ich Module so lade, dass Dateien die im gesamten Modul gebraucht gebraucht werden schon beim import geladen werden und nicht erst die Methode die die Datei braucht diese laden muss. Das gleiche für Datenbanken. Da wäre es aber noch wichtig zu wissen wie ich die Threadsicher mache.

Vielen Dank fürs durchlesen. Ich hoffe ich konnte mich halbwegs verständlich ausdrücken...

Gruß

Christian
BlackJack

@Herr Lehmann: Was für einen I/O-Fehler bekommst Du denn genau?

Ansonsten wäre die Frage was Du da eigentlich wirklich lösen möchtest. ”Möglichst schnell” ist ja kein Selbstzweck und solche globalen Daten sind sehr unschön und unsauber. Ist es denn überhaupt zu langsam wenn Du es ordentlich löst? Kannst Du das mit *gemessenen* Zeiten belegen? Wo genau versprichst Du Dir einen Geschwindigkeitsgewinn?

Wenn ein Datenbankadapter nicht vorsieht, dass eine Verbindung von mehreren Threads aus verwendet werden kann, dann musst Du die Datenbankzugriffe über einen eigenen Thread abwickeln und den dann auch entsprechend ”thread safe” machen.
Herr Lehmann
User
Beiträge: 81
Registriert: Samstag 14. August 2010, 22:20

Der I/O Fehler war File not open for Read

Der Geschwindigkeits unterschied sie so aus.


mit globalen: 0.00239987602234 sek

ohne globale: 0.0039000629425 sek


Die DB und dateien werden größer also weiß ich nicht wie das sich in Zukunft weiter entwickelt. Ich dachte halt es gäb irgendwie enie init methode oder so mit der man sowas elegant lösen kann.
BlackJack

@Herr Lehmann: Der Fehler kann mit dem oben gezeigten Code nicht passieren, denn die Datei *wird* ja zum Lesen geöffnet.

Sind zwei Millisekunden denn tatsächlich ein echtes Problem? Und was heisst ”ohne globale”? Man muss ja nicht in jeder Funktion jedes mal eine neue Verbindung aufbauen, das kann man ja gerne einmal am Anfang machen. Nur eben nicht alleine durch den Import. Eine `__init__`-Methode gibt es bei Klassen. Da Du die Funktionen in dem Modul im ersten Beitrag schon als Methoden bezeichnet hast, möchtest Du vielleicht eigentlich eine Klasse schreiben!?
Herr Lehmann
User
Beiträge: 81
Registriert: Samstag 14. August 2010, 22:20

Wenn bei den 2 ms bleibt ist es kein großes Problem. Ich werde das mal beobachten. Ansonsten muss ich wahrscheinlich meine Programmstruktur überdenken. Das ist mein erstes größeres Python Projekt ( >8000 Zeilen) da hätte ich mir vielleicht mehr Gedanken über die Struktur machen müssen. :roll:
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Faustregel: Über Performance erst dann Gedanken machen, wenn Performance zum tatsächlich spürbaren Problem wird. Ausgenommen sind natürlich Fälle wie `append()`s in einer `for`-Schleife, die man besser als List Comprehension implementiert hätte und sowas in der Art. Das wären ja dann keine "Hacks" oder unnötige Verkomplizierungen des Codes, sondern die schlichte Anwendung von üblichen Sprachkonstrukten.
deets

@snafu
Ausgenommen sind natürlich Fälle wie `append()`s in einer `for`-Schleife, die man besser als List Comprehension implementiert hätte und sowas in der Art.
Seit wann ist das ein Problem?

Code: Alles auswählen

$ python -m timeit "res = []
for x in xrange(100000):
    res.append(x**2)
"
10 loops, best of 3: 23.1 msec per loop

$ python -m timeit "[x**2 for x in xrange(100000)]"
100 loops, best of 3: 13.9 msec per loop
Der Geschwindigkeitsunterschied ist unabhaengig n, etwa Faktor 1.6. Nix, was einen zu Optimierungsorgien treiben wuerde.

[edit]

Und er relativiert sich natuerlich wenn die Operation selbst Komplexer ist - bei x**x wird das dann schon grenzwertig.

[edit2]

"proportional in n" war Bloedsinn.
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@deets: Wenn du den Satz dahinter liest, dann hast du die Antwort. :)
deets

@snafu

Na, mit dem *Beginn* des Satzes kann man da aber auch nicht wirklich drauf kommen...
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Aussage sollte sein: Lesbarkeit über Performance, solange Performance nur theoretisch eine Rolle spielt. Aber trotzdem ruhig idiomatische Konstrukte wie LCs bevorzugen, auch wenn diese performancemäßig in dem Moment noch zu vernachlässig wären. Ich find die Dinger einfach pythonischer.
deets

@snafu

Aber das ist doch genau mein Punkt: so pythonisch sie sein moegen (was ich ja genauso sehe), mit *Performance* hat das nix zu tun. Was du suggerierst.

Eine spaetere Optimierung des codes wird keine messbaren Zuwaechse generieren, weil man explizite for-schleifen durch LCs ersetzt.

Das man LCs einsetzten sollte wo moeglich (und andere idiomatische Konstrukte wie Iteratoren usw.) ist voellig unabhaengig von irgendwelchen Performanceueberlegungen, solange man nicht voellig triviale Ausdruecke auswertet - und selbst dann ist es kaum der Rede wert.
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und genau dies sage ich doch auch (von Anfang an). Ich weiß ehrlich gesagt gerade nicht, was du von mir willst. ^^

EDIT: Achso, ja. Ich war geistig jetzt eher bei der Projektplanung bzw dem ersten Losschreiben, während du das auf nachträgliche Verbesserungen bezogen hast. Beim Refactoring bringt sowas natürlich nicht bedeutend viel, solange man Refactoring auf bloße Performance-Gewinne bezieht. Solche Gewinne durch Nutzung einer LC zu suggieren liegt mir übrigens fern. Mir ging es wirklich nur um's "schöner aussehen". Dein Nachhaken beruht einzig und allein darauf, dass ich die zusätzliche Bemerkung wohl so platziert hatte, dass sie aussah wie eine Relativierung (im Sinne von: Nicht auf Performance achten außer bei LCs). Was ich meinte, war aber: LCs bevorzugen, die sind zwar auch von der Art, dass sie nur ein bißchen was an Performance rauskitzeln können (also deshalb nicht unbedingt benutzt werden sollten), aber gleichzeitig sind sie lesbares Python und sollten eben deshalb genutzt werden (mit dem kleinen genannten Bonbon inklusive). Jetzt klarer? :)

Vielleicht mal in Dialogform: "Hey, ich sehe, dass du eine for-Schleife mit append()s benutzt. Nimm doch lieber eine LC." - "Och, nö. Ich steh' nicht so auf Optimierungen, die nur ein paar Nanosekunden an Speed bringen, dafür aber viel komplizierter zu lesen sind." - "Eine LC ist doch gar nicht komplizierter zu lesen. Das ist eine *Ausnahme* hinsichtlich deines Grundgedankens: Ein Mini-Gewinn, der noch dazu idiomatisches Python ist." "Aaaah, verstehe..." :lol:
Antworten