Инициализация переменной без присвоения значения. Python

Пожалуйста помогите, создал функцию, чтобы приконнектиться к БД, но есть проблема, я не могу дальше пользоваться переменной cursor, чтобы работать с бд.

def ConnectServer():
    cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username.get()+';PWD='+ password.get())
    cursor = cnxn.cursor()

Вопрос: можно ли как-нибудь инициализировать эту переменную в основном коде, без присвоения ей значения?

P.S. Мне нужно, чтобы я мог обращаться к этой переменной при помощи global в функции и она была видна в основном коде

Код кнопки:

bb1 = Button(pas, text='Ввести', background="#555", foreground="#ccc", command=ConnectServer, font='Times 12 italic')

Полный код:


#######################################################################
#######################################################################
def ConnectServer():
    global cursor
    cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username.get()+';PWD='+ password.get())
    cursor = cnxn.cursor()
    root.deiconify()
    pas.withdraw()
#######################################################################
#######################################################################
###Подключение#К#БД###
root = Tk()
root.configure(background='#888')
root.title('СУБД')
root.geometry('1200x600+370+40')
root.withdraw()

server = 'LAPTOP-C0VE2QJR\SERVER' 
database = 'Metropol'
username = StringVar()
password = StringVar()
    
username.set('admin')
password.set('password')
pas = Toplevel(background= "#888")
pas.title('Вход')
pas.geometry('300x300')

Labll = Label(pas, text='Введите логин', font='Times 12 italic', fg='#111')
Labll.grid(row=0, column=0, sticky=S, pady=30, padx=70)

Entr1 = Entry(pas, text='',  textvariable=username, font='Times 12 bold', justify='center')
Entr1.grid(row=1, column=0, sticky=S, padx=70, pady=3)

Labl2 = Label(pas, text='Введите пароль', font='Times 12 italic', fg='#111')
Labl2.grid(row=2, column=0, sticky=S, pady=30, padx=70)

Entr2 = Entry(pas, text='',  textvariable=password, font='Times 12 bold', justify='center')
Entr2.grid(row=3, column=0, sticky=S, padx=70, pady=3)

bb1 = Button(pas, text='Ввести', background="#555", foreground="#ccc", command=ConnectServer, font='Times 12 italic')
bb1.grid(row=4, column=0, sticky=S,  padx=70, pady=10)     
#######################################################################
###Вывод#Таблиц###

cursor.execute("SELECT Номер FROM ЛицевойСчет")
rows = cursor.fetchall()
print(rows)


Ответы (2 шт):

Автор решения: CrazyElf

У вас непонимание, что такое global и как оно работает. Вы спокойно можете объявить переменную как global в функции и присвоить ей что нужно. Она будет далее видна в основной части программы и во всех функциях, где вы её также объявите как global. Никакого предварительного присваивания не нужно при этом.

def ConnectServer():
    global cursor
    cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username.get()+';PWD='+ password.get())
    cursor = cnxn.cursor()

Хотя в любом случае это неправильный шаблон работы с БД. Правильный шаблон - это открывать коннекшен, делать запрос, и закрывать коннекшен. Лучше автоматически - с помощью конструкции with. Современные БД сами следят за тем, чтобы быстро выдавать вам актуальный коннекшен из пула коннекшенов, если вы обращаетесь повторно к той же базе с тем же логином.

А такой шаблон работы, когда вы открываете коннекшен в одном месте, а используете в другом, может привести к различным проблемам. Например, что вы будете делать, если коннекшен прервётся? При нормальном шаблоне работы вам нужно в этом случае попытаться переоткрыть коннекшен и повторить операцию. А как вы это сделаете, если коннекшен вы открываете незнамо где, а вовсе не там, где работаете с базой?

→ Ссылка
Автор решения: vadim vaduxa

Если объект создается внутри функции и присваивается глобальной переменной, то правильнее заранее объявить переменную как None, но использовать аннотацию, как в примере ниже Test: 'Class' = None. Тогда, например PyCharm, будет знать, что это за тип переменной, подтягивать и продолжать названия методов при использовании Test.метод вне функции init_test, сигнализировать при неправильном использовании переменной.

# ---module_1 ---

class Class:
    def method(self):
        return

...

# ---module_2 ---

import module_1
Test: 'module_1.Class' = None

def test():
    global Test
    Test = module_1.Class()
    return

...

# ---module_3---

import module_2
module_2.Test.method()
→ Ссылка