Популярността на Python нарасна експлозивно през последните 5 години. Много нови програмисти са привлечени от него поради плавната му крива на обучение спрямо други езици за програмиране. Опитните програмисти са привлечени от него поради неговата разширяемост и мощност. Въпреки това, един от основните двигатели на това масово усвояване е лекотата, с която Python може да работи с бази данни. Този урок за програмиране на Python ще проучи как да започнете да използвате Python за комуникация със SQL Express с помощта на Python 3.
Програмиране на Python и бази данни
Начинаещ в Python, който желае да интегрира функционалността на базата данни във всякак софтуерен проект, написан на всякакъв езикът трябва да има основно разбиране от поне две езици. Първият, разбира се, е Python, а вторият е специфичният език за структурирани заявки (SQL), използван от базата данни. Въпреки че SQL е стандартизиран, на практика той не е универсален език, но реализациите между различните бази данни са достатъчно близки, така че преминаването от една база данни в друга не е толкова голямо предизвикателство, след като човек има удобно ниво на опит в разработването на приложения за база данни.
Друго важно съображение за базите данни е, че всички те изискват софтуер за управление. Тези инструменти за управление могат да помогнат при настройването на достъп и привилегии за защита в рамките на база данни. Те могат да се използват и за отстраняване на грешки в приложения на база данни, тъй като могат да позволят на разработчика да прави неща като:
- Създаване и управление на съдържанието на таблици, изгледи и други обекти на базата данни. Това включва връзките между таблиците, както и конфигурирането на правилата за интегритет.
- Взаимодействие с базата данни директно чрез въвеждане на SQL код.
- Отстраняване на грешки в SQL синтаксис.
- Отмяна (до известна степен) на щети, причинени от неправилно кодирани SQL изрази в приложението.
Дори ако разработчикът избере да използва базирана на noSQL база данни, като MongoDB, пак ще има предизвикателства при изучаването на специфичния за базата данни синтаксис на кодиране, необходим, за да работи подобно решение. Разбира се, това не са възпиращи фактори, а са просто технически фактори, които трябва да се вземат предвид при всеки проект за разработка на софтуер.
Python и драйвери за бази данни
Python, както всеки друг език за програмиране, не може да комуникира с дадена база данни. Изисква се добавянето на допълнителни модули за конкретен сървър на база данни. От гледна точка на най-добрата практика, най-добре е да използвате модул за драйвер на база данни, който е специфичен за сървъра на базата данни, избран за софтуерния проект. Това гарантира, че Python може да има достъп до всички функции на сървъра на базата данни, дори ако това идва с допълнителната цена от използването на специфичен програмен синтаксис за модула. Въпреки че са правени някои опити за създаване на „универсални“ модули за драйвери на база данни, които могат да се свързват към множество сървъри на бази данни, те често идват за сметка на загуба на достъп до определени функции на конкретен сървър на база данни.
Какво е SQL Express?
SQL Server е решението за сървър на база данни за Windows от десетилетия. Макар че е почти толкова далеч от безплатно решение за сървър на бази данни, колкото може да се получи, Microsoft предоставя нулев разходен вариант на SQL Server, наречен SQL Express. SQL Express е идеален инструмент за обучение за начинаещи, тъй като поддържа същия SQL синтаксис, който използва SQL Server. И SQL Express, и SQL Server използват персонализирано разширение на SQL, наречено „Transact-SQL“, известно още като „T-SQL“. И SQL Express, и SQL Server поддържат използването на потребителски акаунти на Windows и традиционни системи за потребителско име и парола за управление на достъпа.
Python комуникира със SQL Express или SQL Server с модул с име PyODBC . И SQL Server, и SQL Express се управляват от отделно Windows приложение с нулева цена, наречено „SQL Server Management System“, популярно известно като „SSMS“. Към момента на писане и SQL Express, и SSMS са отделни изтегляния от Microsoft:
- Изтегляне на SSMS
- Изтегляне на SQL Express
Как да конфигурирате SQL Express за разработка на Python
SQL Express, подобно на SQL Server, поддържа два вида удостоверяване. Първият е удостоверяване въз основа на потребителския акаунт в Windows на потребител, известен също като „Надеждена връзка“. Вторият е традиционното удостоверяване, базирано на потребителско име и парола, се прилага в така нареченото „удостоверяване в смесен режим“. Удостоверяването в смесен режим поддържа както удостоверяване, базирано на потребителски акаунт на Windows, така и удостоверяване, базирано на потребителско име и парола. Няма начин да се поддържа самостоятелна автентификация, базирана на потребителско име и парола, в SQL Server или SQL Express.
Microsoft се отдалечава от удостоверяването в смесен режим, тъй като едно от основните предимства на използването на доверени връзки е, че идентификационните данни на базата данни не трябва да се съхраняват в кода на приложението. Демонстрацията в тази статия също няма да го използва.
НЕ копира низа за връзка след инсталиране
Една от спорните точки за разработчиците на приложения на ниво начинаещи е първоначалното объркване около низовете за връзка на SQL Server. Ако някой инсталира SQL Express, инсталационната програма предоставя низа за свързване за създадения екземпляр на SQL Express след инсталиране. За съжаление предоставеният низ за връзка вероятно няма да работи с PyODBC . Въпреки че е изкушаващо да бъдете „приспивни“ в чувство за сигурност с тази „безплатна услуга“, това ще причини повече проблеми, отколкото си струва.
Фигура 1 – Получаване на низа за връзка от инсталатора на SQL Express
Имайте предвид, че към момента на писане на това писане инсталационната програма за SQL Express включва и връзка за изтегляне на инсталационната програма SSMS.
Как да създадете база данни в SQL Express
След като SQL Express и SSMS бъдат инсталирани, е време да създадете основна база данни с подходящи ограничения за достъп. Най-лесният начин да стартирате SSMS е да щракнете върху Старт бутон в Windows, въведете „ssms“ в лентата за търсене, изчакайте „Microsoft SQL Server Management Studio 18“ да се появи в горния десен ъгъл и след това щракнете върху Отваряне връзка в дясната част на панела на менюто "Старт":
Фигура 2 – Стартиране на SSMS
При стартиране на SSMS човек се поздравява от следния диалогов прозорец:
Фигура 3 – Диалог за отваряне на SSMS
С удостоверяването на Windows няма нужда да въвеждате никакви идентификационни данни. Потребителският акаунт на Windows под който е инсталиран SQL Express има административни привилегии за екземпляра на SQL Express. Просто щракнете върху Свързване за да продължите.
В най-лявата страна на прозореца на приложението SSMS , ще има Object Explorer . За да създадете нова база данни, щракнете с десния бутон върху Бази данни и изберете Създаване на база данни от контекста меню:
Фигура 4 – Създаване на нова база данни – Част 1 от 2
Щракнете върху Нова база данни... ще отвори нов диалогов прозорец, който позволява да бъдат въведени данните за новата база данни. За тази демонстрация базата данни ще се нарича RazorDemo , като малко връщане към предишна статия за разработване на базирани на Razor приложения в C#. Въведете името на базата данни в текстовото поле до Име на базата данни и след това щракнете върху OK бутон в долната част на диалоговия прозорец. Имайте предвид, че в илюстрацията по-долу колоните за Логическо име от файловете бяха леко разширени, така че пълните Логически имена от създадените файлове на базата данни бяха изложени:
Фигура 5 – Създаване на нова база данни – Част 2 от 2
След това новата база данни ще се появи в Object Explorer под Бази данни папка:
Фигура 6 – Новосъздадената база данни „RazorDemo“
Как да създавате таблици в SQL Express
Релационната база данни не е наистина полезна без таблици за съхраняване на данните и най-лесният начин за създаване на тези таблици е да използвате SQL код. Имайте предвид, че може да се използва Съветникът за създаване на таблица за да създадете таблица, използването на SQL код е по-бързо, по-лесно и много по-лесно. Започнете, като щракнете с десния бутон върху RazorDemo запис в базата данни, след което щракнете с левия бутон върху Нова заявка опция в контекстния прозорец:
Фигура 7 – Отваряне на нов прозорец за заявка
Прозорец на редактора на заявки, подобен на този по-долу, ще се появи вдясно от Object Explorer :
Фигура 8 – Прозорецът на редактора на заявки
Кодът за създаване на таблица е показан в списъка по-долу:
use RazorDemo; # See the Important Note below create table artists (rcdid int not null identity primary key, artist_name varchar(max)); create table albums (rcdid int not null identity primary key, artist_id int not null references artists(rcdid) on delete cascade, album_name varchar(max)); Listing 1 - Table Creation SQL Code
Забележете, докато създавате Прозорец на редактора на заявки от базата данни обикновено гарантира, че избраната база данни ще бъде тази, срещу която се изпълнява кодът, е добра идея винаги изрично използва предвидената база данни в началото на кода. Използването команда изрично избира името на базата данни, която я следва.
Натискане на F5 или щракнете върху Изпълни бутон ще изпълни операторите срещу RazorDemo база данни. Ако изпълнението е успешно, съобщение, което го указва, ще се появи в „Съобщения поле по-долу:
Фигура 9 – Успешно създаване на таблица
Новосъздадените таблици и техните колони могат да се видят в Object Explorer също така. Имайте предвид, че понякога Опресняване опция от контекстното меню, което се появява при щракване с десния бутон върху базата данни, може да се наложи да бъде избрана, за да се покажат нови обекти в базата данни:
Фигура 10 – Обновяване на Object Explorer
Фигура 11 – Новите таблици и техните колони
В този момент SSMS може да бъде безопасно затворен.
Имайте предвид, че SSMS работи по същия начин и с всяка база данни на SQL Server. Винаги е най-добрата практика да запазите целия код за създаване на таблица, независимо кой сървър на база данни се използва. Въпреки че SQL Server и SQL позволяват възстановяване на такива скриптове, и двата позволяват използването на криптиране и за такива изрази и в тези случаи кодът не може да бъде възстановен.
Python и SQL Express
Обикновено тук ще е необходима дискусия за сигурността на SQL Server, но тъй като Надеждени връзки ще се използва, стига изпълняващият се процес, изпълняващ кода на Python, е собственост на Потребител на Windows който вече има достъп до база данни, до която се осъществява достъп, тази дискусия няма да е необходима. Имайте предвид, че както SQL Server, така и SQL Express предлагат много стабилни персонализации, свързани със сигурността, но те са извън обхвата на статия, предназначена за начинаещи.
Забележете, не пренебрегвайте правилната защита на базата данни за всяко приложение, работещо в производствена среда! Уверете се, че на потребителския акаунт, който ще има достъп до база данни в прожекционна среда, са дадени само възможно най-малко привилегии.
Версията на Python, използвана за тези примери за код, е 3.10 и е инсталирана чрез Microsoft Store в Windows. Инсталирането на Python с този метод ще добави изпълними файлове на Python и PIP3 към системния път, така че пълните пътища до тези команди няма да е необходимо да се въвеждат в командния ред прозорци. За въвеждане на код добър текстов редактор с нулева цена е Notepad++.
Отваряне на командния ред на Windows
Изпълнението на Python код се извършва най-добре чрез Командния ред . За достъп до командния ред , щракнете върху Старт бутон в Windows и въведете cmd в лентата за търсене. Изчакайте командния ред за да се появи и след това щракнете върху Отваряне връзка от дясната страна на менюто "Старт" :
Фигура 12 – Отваряне на команден ред
Типичен команден ред прозорецът изглежда така:
Фигура 13 – Типичен команден ред
Как да инсталирате PyODBC
PyODBC е модулът на Python, който позволява на Python достъп както до SQL Server, така и до SQL Express. При инсталиране на Python чрез Microsoft Store, PyODBC може да се добави към Python чрез командата:
pip3 install pyodbc
Фигура 14 – Успешна инсталация на PyODBC
Забележете, ако има инсталирани множество версии на Python, например Python 2 и Python 3, може да се наложи да поставите префикс на pip3 команда с пълния път на WIndows до командата за съответната версия на Python.
Също така имайте предвид, че ако е инсталиран само Python 3, pip3 командата все още трябва да се използва над по-генеричния pip команда, тъй като това е правилната конвенция.
Писане на Python код
Сега, когато базата данни е конфигурирана и PyODBC са инсталирани, базата данни може да бъде попълнена. В случай на база данни, която каталогизира изпълнители и албуми, някои произволно генерирани имена на групи и албуми ще бъдат достатъчни. Кодът на Python за свързване към базата данни също е включен, но вмъкванията не са (все още):
# bad-band-name-maker.py import sys import random import pyodbc part1 = ["The", "Uncooked", "Appealing", "Larger than Life", "Drooping", "Unwell", "Atrocious", "Glossy", "Barrage", "Unlawful"] part2 = ["Defeated", "Hi-Fi", "Extraterrestrial", "Adumbration", "Limpid", "Looptid", "Cromulent", "Unsettled", "Soot", "Twinkle"] part3 = ["Brain", "Segment", "Audio", "Legitimate Business", "Mentality", "Sound", "Canticle", "Monsoon", "Preserves", "Hangout"] part4 = ["Cougar", "Lion", "Lynx", "Ocelot", "Puma", "Jaguar", "Panther"] part5 = ["Fodder", "Ersatz Goods", "Leftovers", "Infant Formula", "Mush", "Smoothie", "Milkshakes"] def main(argv): # Connect to the RazorDemo database. conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=localhost\SQLEXPRESS;Database=RazorDemo;Trusted_Connection=yes;") # Generate 15 bad band names: for x in range(1, 16): rand1 = random.randrange(0, 9) rand2 = random.randrange(0, 9) rand3 = random.randrange(0, 9) badName = part1[rand1] + ' ' + part2[rand2] + ' ' + part3[rand3] print ("Band name [" + str(x) + "] is [" + badName + "]") for y in range(1, 3): rand4 = random.randrange(0, len(part4)) rand5 = random.randrange(0, len(part5)) albumName = part4[rand4] + " " + part5[rand5] print ("\tAlbum [" + albumName + "]") # Close the Connection conn.close() return 0 if __name__ == "__main__": main(sys.argv[1:]) Listing 2 - Making up some data
Това дава следния изход:
Фигура 15 – Случайно генерирани имена на групи
Обърнете внимание на използването на cd команда, за да преминете към директорията, където е записан кодът на Python. PyODBC connect() функцията няма да успее, ако Потребителският акаунт на Windows е влязъл в момента не е посочен като имащ достъп в SQL Express. Това е проблем само ако базата данни е създадена с един Потребителски акаунт на Windows но кодът се изпълнява под различен Потребителски акаунт на Windows .
Най-малко лошият начин за ВМЕСВАНЕ на данни в SQL и PyODBC
Много начинаещи разработчици на Python се изкушават да извършват извиквания към PyODBC извиква INSERT изрази в следващите раздели на кода и в контекста на това, което ще бъде посочено по-нататък, това не е лоша идея:
Фигура 16 – „Почти“ грешен начин за работа с база данни
Причината, поради която се използват извиквания към PyODBC за извършване на INSERTs , SELECTs и други функции, свързани с базата данни, като UPDATE или ИЗТРИВАНЕ , в рамките на цикли може да е лошо, защото има режийни разходи, които идват с всяко от тези повиквания. В рамките на цикъл, който потенциално може да повтори стотици пъти, хиляди пъти или дори повече, това може да доведе до значителен период от време (минути или повече) за изпълнение на скрипт. За уеб приложенията, които използват такъв подход, проблемите с производителността се задълбочават допълнително, тъй като много уеб сървъри налагат твърдо ограничение на времето, през което даден скрипт може да се изпълнява. Никога при никакви обстоятелства не предавайте въведените от потребителя данни директно в база данни. Винаги проверявайте входа, за да се уверите, че няма да наруши функционалността на базата данни или да причини проблем със сигурността чрез атака с инжектиране на SQL.
В идеалния случай човек би искал да използва циклите по-горе, за да създаде SQL пакет (списък с изрази) и след това да има PyODBC стартирайте на тази единична партида, но това би било много лоша идея, ако данните не са дезинфекцирани.
Защо данните трябва да бъдат дезинфекцирани? Причината се свежда до сигурността, тъй като потребителският вход никога не може да се вярва. Санитаризирането на данните означава представянето им по начин, който предотвратява изпълнението на нещо различно от SQL израза, създаден от разработчика на програмата. Потребителят може да предаде злонамерено конструиран низ, който би позволил изпълнението на произволно създаден SQL код. Това е известно като атака с SQL инжекция. Докато стойностите на данните, влизащи в пакет, могат да бъдат дезинфекцирани, процесът за това е извън обхвата на въвеждащ урок.
PyODBC осигурява механизъм за защита на базата данни от атаки с инжектиране на SQL чрез дезинфекция на въведените от потребителя данни. Те включват използването на параметризирани изрази , наричан също подготвени изявления . Сигурността винаги трябва да бъде приоритет, дори ако това е за сметка на скоростта или други показатели за ефективност.
Потребителският акаунт на Windows, който има достъп до тази база данни, има по подразбиране права на системен администратор. Това означава, че ако възникне атака с SQL инжекция, злонамерен потребител може да получи достъп до всички данни във всяка база данни на сървъра. На практика нито един акаунт с привилегии на системен администратор не трябва да има достъп до база данни от код на Python.
Списъкът по-долу допълва първия пример за код на Python, като използва PyODBC курсори за вмъкване на данните:
# bad-band-name-maker2.py import sys import random import pyodbc part1 = ["The", "Uncooked", "Appealing", "Larger than Life", "Drooping", "Unwell", "Atrocious", "Glossy", "Barrage", "Unlawful"] part2 = ["Defeated", "Hi-Fi", "Extraterrestrial", "Adumbration", "Limpid", "Looptid", "Cromulent", "Unsettled", "Soot", "Twinkle"] part3 = ["Brain", "Segment", "Audio", "Legitimate Business", "Mentality", "Sound", "Canticle", "Monsoon", "Preserves", "Hangout"] part4 = ["Cougar", "Lion", "Lynx", "Ocelot", "Puma", "Jaguar", "Panther"] part5 = ["Fodder", "Ersatz Goods", "Leftovers", "Infant Formula", "Mush", "Smoothie", "Milkshakes"] def main(argv): # Connect to the RazorDemo database. conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=localhost\SQLEXPRESS;Database=RazorDemo;Trusted_Connection=yes;") # Generate 15 bad band names, and try to keep them unique. previousNames = "" nameCount = 0 while (nameCount < 16): rand1 = random.randrange(0, 9) rand2 = random.randrange(0, 9) rand3 = random.randrange(0, 9) badName = part1[rand1] + ' ' + part2[rand2] + ' ' + part3[rand3] # A crude but effective way of ensuring uniqueness, although there is no unique constraint on the artist name in the database. # This prepends and appends bars to both the list of previously used names and the current name. If the current name is # new, it will not be in that string. if ("|" + previousNames + "|").find("|" + badName + "|") == -1: print ("Band name [" + str(nameCount) + "] is [" + badName + "]") sql1 = "insert into artists (artist_name) values (?)" values1 = [badName] rs1 = conn.cursor() rs1.execute(sql1, values1) rs1.commit() # If the cursor is not closed, then other cursors cannot be executed. rs1.close() for y in range(1, 3): rand4 = random.randrange(0, len(part4)) rand5 = random.randrange(0, len(part5)) albumName = part4[rand4] + " " + part5[rand5] print ("\tAlbum [" + albumName + "]") sql2 = "insert into albums (artist_id, album_name) values ((select top 1 rcdid from artists where artist_name=?), ?)" # Each array item here corresponds to the position of the ? in the SQL statement above. values2 = [badName, albumName] rs2 = conn.cursor () rs2.execute(sql2, values2) rs2.commit() rs2.close() # Creates a bar-delimited list of previously used names. if previousNames == "": previousNames = badName else: previousNames = previousNames + "|" + badName nameCount = 1 + nameCount else: print ("Found a duplicate of [" + badName + "]") #print (previousNames) # Close the Connection conn.close() return 0 if __name__ == "__main__": main(sys.argv[1:]) Listing 3 - Inserting the data
Следната заявка може да се изпълни в SSMS, за да се провери изходът на кода:
Фигура 17 – Успешно вмъкване на данните
Избиране на данни в SQL Express и Python
Сега, когато има данни в базата данни, би било хубаво да ги потърсите. По-долу е даден прост скрипт, който приема потребителски данни от клавиатурата, предава ги в базата данни чрез параметризирана заявка:
# bad-band-name-maker3.py import sys import pyodbc def main(argv): searchValue = input("Enter something: ") # Cap the length at something reasonable. The first 20 characters. searchValue = searchValue[0:20] # Set the search value to lower case so we can perform case-insensitive matching: searchValue = searchValue.lower() # Connect to the RazorDemo database. conn = pyodbc.connect("Driver={ODBC Driver 17 for SQL Server};Server=localhost\SQLEXPRESS;Database=RazorDemo;Trusted_Connection=yes;") # You must use a parameterized query here in order to protect from SQL Injection Attacks! # For the like operator, the percent signs must be separated from the term or else the parameterization will fail. sql1 = ("select a.artist_name, b.album_name from artists a, albums b where b.artist_id = a.rcdid and " + "lower(album_name) like ('%' + ? + '%') order by a.artist_name, b.album_name") # Below is an array with one element: values1 = [searchValue] rs1 = conn.cursor() rs1.execute(sql1, values1) rows1 = rs1.fetchone() #print ("Type is [" + str(type(rows1)) + "]") if str(type(rows1)).find("NoneType") == -1: while rows1: # Columns are indexed by number only. 0 is the a.artist_name column and 1 is the b.album_name columns print(rows1[0] + " - " + rows1[1]) rows1 = rs1.fetchone() else: print ("No album name matched [" + searchValue + "]") # Close the Connection conn.close() return 0 if __name__ == "__main__": main(sys.argv[1:]) Listing 4 - Querying the Data
Същите резултати. Едната дори включва пример за груба атака с SQL инжекция:
Фигура 18 – Резултати от заявката. Забележете последната стойност за търсене.
Окончателни мисли за разработването на база данни на Python
Наистина няма ограничение за това какви приложения, управлявани от SQL Server, могат да бъдат разработени с помощта на Python. Разработчикът е ограничен само от познанията по SQL и се надяваме, че основните концепции, представени в тази статия, могат да насочат разработчик от ниво начинаещ в правилната посока по отношение на разширяване на разбирането на SQL и изграждане на по-сложни приложения.
Този урок за програмиране на база данни на Python представи средства, чрез които SQL Express може да бъде инсталиран като помощно средство за развитие на SQL Server и показа как Python 3 може да бъде разширен, за да комуникира правилно с екземпляр на база данни SQL Express на този сървър. Тази статия също така показа как SQL Server Management Studio трябва да се използва за управление на SQL Express или SQL Server бази данни. Продължавайки по-нататък, тази статия засяга и основните предпазни мерки за сигурност и използването на ефективно кодиране за целите на осигуряване на разумно време за изпълнение за приложения, управлявани от SQL Server.