» »

[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:

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
  • spremenilo: HotBurek ()

HotBurek ::

Evo, sedaj gledam, kako preverit za None type.

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

Zgodovina sprememb…

  • spremenilo: HotBurek ()

kow ::

Malo si se izgubil, burek.

Bos moral pogledati v kodo (ali dokumentacijo) za connect().

HotBurek ::

Evo, šel na break in je pomagalo.

# 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

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

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:

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

Zgodovina sprememb…

  • spremenilo: HotBurek ()

FireSnake ::

A kdo tega pajaca še resno jemlje v tem sklopu?
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

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

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.
Poglej in se nasmej: vicmaher.si

Zgodovina sprememb…

kow ::

Zna biti, da je trol, da.

Ahim ::

HotBurek je izjavil:

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.
root@debian:/# iptraf-ng
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#.

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 ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

SQL problem

Oddelek: Programiranje
141688 (1306) win64
»

Napaka pri povezavi z bazo - c#

Oddelek: Programiranje
71008 (872) Mitja Bonča
»

C# OleDB create database

Oddelek: Programiranje
71308 (1140) DubleG
»

Statistika dijakov, pomoc

Oddelek: Programiranje
211783 (1267) Mitja Bonča
»

[C#] DATA GRID VIEW

Oddelek: Programiranje
131943 (1823) Kekec

Več podobnih tem