Forum » Programiranje » [Try/Except/Finally] - Kako pravilno zapreti povezavo na SQL bazo v Python-u?
[Try/Except/Finally] - Kako pravilno zapreti povezavo na SQL bazo v Python-u?
HotBurek ::
Dobro jutro.
Evo, novo popoldne, nov izziv.
Tokrat me zanima, kako se pravilno piše try/except/finally, kadar dostopamo do SQL baze?
Nekaj na to temo je razloženo tule: https://stackoverflow.com/questions/171...
V osnovi je tako, da tisto, kar je definirano v try bloku, je na voljo tudi izven. Vsaj za Python bi naj bilo tako.
Enostaven primer kode:
Vprašanje 1
Ali je pravilno, da se povezavo zapira v try blok-u ( sql_connection.close(); ), ali to spada v finally blok?
Vprašanje 2
Če bi ob poizkusu vzpostavitve povezave prišlo do napake ( sql_connection = sql_engine.connect(); ), ugibam, da bi sql_connection lahko bil null. Verjetno je potrebno potem to dodatno hendlat pri zapiranju ( close(); ) in preverit if null, v kolikor bi zapiranje prestavil v finally blok. Al ne?
Evo, novo popoldne, nov izziv.
Tokrat me zanima, kako se pravilno piše try/except/finally, kadar dostopamo do SQL baze?
Nekaj na to temo je razloženo tule: https://stackoverflow.com/questions/171...
V osnovi je tako, da tisto, kar je definirano v try bloku, je na voljo tudi izven. Vsaj za Python bi naj bilo tako.
Enostaven primer kode:
import sqlalchemy; # sql host sqlhost = "mysql://vinko:trdo_geslo@localhost:3306/?autocommit=true&charset=utf8mb4"; # set sql engine sql_engine = sqlalchemy.create_engine(sqlhost, future=True); # try execute try: # make sql connection sql_connection = sql_engine.connect(); # TODO # make some sql damage... # close connection sql_connection.close(); except: # don't care pass; finally: # dispose sql engine sql_engine.dispose();
Vprašanje 1
Ali je pravilno, da se povezavo zapira v try blok-u ( sql_connection.close(); ), ali to spada v finally blok?
Vprašanje 2
Če bi ob poizkusu vzpostavitve povezave prišlo do napake ( sql_connection = sql_engine.connect(); ), ugibam, da bi sql_connection lahko bil null. Verjetno je potrebno potem to dodatno hendlat pri zapiranju ( close(); ) in preverit if null, v kolikor bi zapiranje prestavil v finally blok. Al ne?
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
- spremenilo: HotBurek ()
HotBurek ::
Evo, sedaj gledam, kako preverit za None type.
Koda:
Output:
Vir: https://stackoverflow.com/questions/230...
Krneki. Time for break;
Koda:
var1 = None; print(type(var1)); if type(var1) is not None: print("a"); else: print("b");
Output:
<class 'NoneType'> a
Vir: https://stackoverflow.com/questions/230...
Krneki. Time for break;
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
Zgodovina sprememb…
- spremenilo: HotBurek ()
HotBurek ::
Evo, šel na break in je pomagalo.
Let's continue.
# narobe if type(sql_connection) is not None: # pravilno if sql_connection is not None:
Let's continue.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
Zgodovina sprememb…
- spremenilo: HotBurek ()
HotBurek ::
Evo, tole je trenutno končna verzija (close prestavljen v finally plus some checks) in s tem bom šel naprej.
finally: # check sql connection if exists if "sql_connection" in locals(): # and not none if sql_connection is not None: # close connection sql_connection.close(); # dispose sql engine sql_engine.dispose();
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
Zgodovina sprememb…
- spremenilo: HotBurek ()
HotBurek ::
V vednost, zakaj gnezdenje "if v if". Ker v zgornjem primeru "pogoj1 AND pogoj2" ne vrne isti rezultat (za isti input), kot "pogoj2 AND pogoj1".
Simple.
Primer 1:
V prvem primeru prvo preveri ali prvi pogoj vrne true, in ker vrne false, ne nadaljuje z preverjanjem (ker vsaj logično ni smiselno), ter izvede "else" del (print b).
Primer 2:
V drugem primeru prav tako preveri, ali prvi pogoj vrne true, in ker test1 ni definiran, dobimo error:
Res je, da bi lahko uporabil prvo verzijo (prvo preverba z locals), ampak lahko kdaj v prihodnosti zaradi bilo česa spremeniš vrstni red, ker pač to narediš. Če imaš pa nestan if, pa s tem po svoje jasno definiraš vrstni red.
Well done.
Simple.
Primer 1:
if "test1" in locals() and test1 is not None: print("a"); else: print("b");
V prvem primeru prvo preveri ali prvi pogoj vrne true, in ker vrne false, ne nadaljuje z preverjanjem (ker vsaj logično ni smiselno), ter izvede "else" del (print b).
Primer 2:
if test1 is not None and "test1" in locals(): print("a"); else: print("b");
V drugem primeru prav tako preveri, ali prvi pogoj vrne true, in ker test1 ni definiran, dobimo error:
NameError: name 'test1' is not defined
Res je, da bi lahko uporabil prvo verzijo (prvo preverba z locals), ampak lahko kdaj v prihodnosti zaradi bilo česa spremeniš vrstni red, ker pač to narediš. Če imaš pa nestan if, pa s tem po svoje jasno definiraš vrstni red.
Well done.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
Zgodovina sprememb…
- spremenilo: HotBurek ()
FireSnake ::
A kdo tega pajaca še resno jemlje v tem sklopu?
Sploh ni več smešno.
Sploh ni več smešno.
Poglej in se nasmej: vicmaher.si
ReRMh ::
menim, da gre za tutorial po inkluzivni metodi, ne strogo spoon-feeding...
na eni strani se predstavi problem za malo debate, nato prinese rešitev (ali del rešitve)
mene osebno ne moti, še zabavno je po svoje...
žal sem pa samo navaden, nepomemben in brezimen siromak
na eni strani se predstavi problem za malo debate, nato prinese rešitev (ali del rešitve)
mene osebno ne moti, še zabavno je po svoje...
žal sem pa samo navaden, nepomemben in brezimen siromak
Zgodovina sprememb…
- spremenilo: ReRMh ()
acookook ::
Ne moti, da eni toliko spamajo, čeprav na koncu veeno znajo rešiti stvar, med tem pa ko drugi kaj vprašamo nikome ništa oziroma se zaradi takih pajacev post(i) drugih izgubi(jo)
.
ReRMh ::
tu je več možnih razlag :D
nesankcioniranega (družboslovnega) spama je daleč največ...
mogoče so nekatera vprašanja preveč kompleksna in zahtevajo preveč napora,
možno, da nekateri ne opazijo vprašanj pravočasno ali jim je gladko vseeno,
lahko se da rešiti s poenostavljenimi prototipi, chatgpt ali podobnim orodjem
nemogoče niti ni zavestno ignoriranje vprašanj
nesankcioniranega (družboslovnega) spama je daleč največ...
mogoče so nekatera vprašanja preveč kompleksna in zahtevajo preveč napora,
možno, da nekateri ne opazijo vprašanj pravočasno ali jim je gladko vseeno,
lahko se da rešiti s poenostavljenimi prototipi, chatgpt ali podobnim orodjem
nemogoče niti ni zavestno ignoriranje vprašanj
Zgodovina sprememb…
- spremenilo: ReRMh ()
FireSnake ::
Iz tehničnega vidika: veliko vprašanj je vprašano na način, da odgovor sploh ni možen, ker manjka preveč informacij.
In potem tokom odgovarjanja samemu sebi navrže še par drobtinic, ki bi jih moral že v otvoritvenem postu.
In, če bi vsa informacija bila podana takoj bi bil odziv večji (lahko napišemo tudi: sploh možen). Tako pa velikokrat samo gledam kaj se temu osebku plete v glavi.
Tu smo zato, da pomagamo, ni problema. A se hitro vidi kdo pa trola. In moje mnenje je (po vsem, kar sem prebral), da imamo opravka s trolom.
In potem tokom odgovarjanja samemu sebi navrže še par drobtinic, ki bi jih moral že v otvoritvenem postu.
In, če bi vsa informacija bila podana takoj bi bil odziv večji (lahko napišemo tudi: sploh možen). Tako pa velikokrat samo gledam kaj se temu osebku plete v glavi.
Tu smo zato, da pomagamo, ni problema. A se hitro vidi kdo pa trola. In moje mnenje je (po vsem, kar sem prebral), da imamo opravka s trolom.
Poglej in se nasmej: vicmaher.si
Zgodovina sprememb…
- spremenilo: FireSnake ()
Ahim ::
Evo, tole je trenutno končna verzija (close prestavljen v finally plus some checks) in s tem bom šel naprej.
finally:
# check sql connection if exists
if "sql_connection" in locals():
# and not none
if sql_connection is not None:
# close connection
sql_connection.close();
# dispose sql engine
sql_engine.dispose();
En namig: try bloke lahko poljubno gnezdis. Pravilno (ce ze uporabljas try bloke) bi bilo, da za vsak stvar, ki zahteva catch in/ali finally, naredis svoj try blok, ne pa da v enega zmeces vse, potem pa z mnozico ifov preverjas ali se moras dotakniti se tegaintega ali ne.
V tem konkretnem primeru zgoraj je prvi blok za instancirat (in disposat) engine, en nivo globlje pa za instancirat (in zapret) connection.
V praksi najbrz ne bi vzpostavljal vsega znova za vsaki query.
Pojdi v knjiznico in si izposodi kaksno knjigo o osnovah programiranja (ali pa najdi kaj primernega online).
HotBurek ::
Dobro jutro.
1. Dalnega leta sem bral knjigo (C#), in po spominu pravi, da vsak try/catch zahteva dodaten memory, in več je tega (try/catch), več memorija program popapca (vsaj za čas izvajanja).
Ker če to okrog memorija ni res, potem bi lahko celoten program, vsako funkcijo in vsak ukaz dali "pod" try/catch in bi bil 100% safe.
2. Čisto osebna preferenca, da mi koda, kjer je try v try, ni gut. Edina izjema je, če znotraj try bloka kličem funkcijo, ki ima delno nek segmet pod try/catch.
3. Kar se tiče da "vse zmečeš v enega". Well, v try so v osnovi samo trije kuazi: connect, execut, close. No, sedaj, ko sem premaknil close v finally, še tega ni tam: v try sta praviloma samo dva ukaza (connect, execute).
Sem pa sedajle naredil test in videl, da lahko ukaz dispose naredim tudi izven finally, kar pomeni da je v finally bloku samo en ukaz za (close).
UPDATE
Šel sem brat dokumentacijo.
https://docs.sqlalchemy.org/en/13/core/...
In ugotovil, da delam narobe, saj vsakič (za vsak sql ukaz) generiram nov engine, in ga kasneje dispos-am. Kar, kot pravi dokumentacija, se tako za pravega moškega ne spodobi (navedenih robnih primerov pa nimam).
Torej, bom popravil in engine prestavil na "global" nivo in ga za celotno seanso programa kreiral (na začetku) in disposal (na koncu) samo enkrat.
Let's go.
1. Dalnega leta sem bral knjigo (C#), in po spominu pravi, da vsak try/catch zahteva dodaten memory, in več je tega (try/catch), več memorija program popapca (vsaj za čas izvajanja).
Ker če to okrog memorija ni res, potem bi lahko celoten program, vsako funkcijo in vsak ukaz dali "pod" try/catch in bi bil 100% safe.
2. Čisto osebna preferenca, da mi koda, kjer je try v try, ni gut. Edina izjema je, če znotraj try bloka kličem funkcijo, ki ima delno nek segmet pod try/catch.
3. Kar se tiče da "vse zmečeš v enega". Well, v try so v osnovi samo trije kuazi: connect, execut, close. No, sedaj, ko sem premaknil close v finally, še tega ni tam: v try sta praviloma samo dva ukaza (connect, execute).
Sem pa sedajle naredil test in videl, da lahko ukaz dispose naredim tudi izven finally, kar pomeni da je v finally bloku samo en ukaz za (close).
UPDATE
Šel sem brat dokumentacijo.
https://docs.sqlalchemy.org/en/13/core/...
In ugotovil, da delam narobe, saj vsakič (za vsak sql ukaz) generiram nov engine, in ga kasneje dispos-am. Kar, kot pravi dokumentacija, se tako za pravega moškega ne spodobi (navedenih robnih primerov pa nimam).
Torej, bom popravil in engine prestavil na "global" nivo in ga za celotno seanso programa kreiral (na začetku) in disposal (na koncu) samo enkrat.
Let's go.
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
Zgodovina sprememb…
- spremenilo: HotBurek ()
DamijanD ::
Exceptioni so res dražji od navadnih stavkov (vsaj pri .NETu/C#), ampak to še ne pomeni, da se ne smejo uporabljat. Ne vem pa kako ima to implementirano python (oz. karkoli ti uporabljaš)
Ima pa C# za take probleme blok using, kar si verjetno zasledil v knjigi, ker mislim, da je prisoten od prve verzije C#.
Ima pa C# za take probleme blok using, kar si verjetno zasledil v knjigi, ker mislim, da je prisoten od prve verzije C#.
kow ::
Drazji? A bo Burek izgubil kaksno milisekundo zivljenja al kaj? Vas skrbi za 0.00000000001e visji racun za elektriko?
Zgodovina sprememb…
- spremenil: kow ()
kr?en ::
OP, dej si pejt raj prebrat kako knjigo o Pythonu in kako dela DB lib preden zacnes odpirat glupe topice.
jan_g ::
Poglej si Python context managerje (in 'with' ukaz). Engine s connection pool-om inicializiraš enkrat, ne pa za vsakič, ko poganjaš query. In tako dalje.
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | SQL problemOddelek: Programiranje | 1688 (1306) | win64 |
» | Napaka pri povezavi z bazo - c#Oddelek: Programiranje | 1008 (872) | Mitja Bonča |
» | C# OleDB create databaseOddelek: Programiranje | 1308 (1140) | DubleG |
» | Statistika dijakov, pomocOddelek: Programiranje | 1783 (1267) | Mitja Bonča |
» | [C#] DATA GRID VIEWOddelek: Programiranje | 1943 (1823) | Kekec |