Python ha crecido explosivamente en popularidad en los últimos 5 años. Muchos programadores nuevos se sienten atraídos por su suave curva de aprendizaje en relación con otros lenguajes de programación. Los programadores experimentados se sienten atraídos por él debido a su extensibilidad y potencia. Sin embargo, uno de los principales impulsores de esta adopción masiva es la facilidad con la que Python puede trabajar con bases de datos. Este tutorial de programación de Python explorará cómo comenzar a usar Python para comunicarse con SQL Express usando Python 3.
Python y programación de bases de datos
Un principiante de Python que desee integrar la funcionalidad de la base de datos en cualquier proyecto de software escrito en any idioma debe tener una comprensión básica de al menos dos idiomas El primero es, por supuesto, Python y el segundo es el lenguaje de consulta estructurado (SQL) específico que utiliza la base de datos. Si bien SQL está estandarizado, en la práctica no es un lenguaje universal, pero las implementaciones entre varias bases de datos son lo suficientemente cercanas como para que pasar de una base de datos a otra no sea un gran desafío una vez que uno tiene un nivel cómodo de experiencia en el desarrollo de aplicaciones de bases de datos.
Otra consideración importante para las bases de datos es que todas requieren un software de gestión. Estas herramientas de administración pueden ayudar a configurar el acceso y los privilegios de seguridad dentro de una base de datos. También se pueden usar para depurar aplicaciones de bases de datos, ya que pueden permitir que un desarrollador haga cosas como:
- Creación y gestión del contenido de tablas, vistas y otros objetos de base de datos. Esto incluye las relaciones entre tablas, así como la configuración de reglas de integridad.
- Interacción con la base de datos directamente a través de la entrada de código SQL.
- Depuración de sintaxis SQL.
- Deshacer (hasta cierto punto) el daño causado por declaraciones SQL codificadas incorrectamente en la aplicación.
Incluso si un desarrollador elige usar una base de datos basada en noSQL como MongoDB, aún habrá desafíos para aprender la sintaxis de codificación específica de la base de datos necesaria para que dicha solución funcione. Por supuesto, estos no son impedimentos, son solo factores técnicos que deben tenerse en cuenta en cualquier proyecto de desarrollo de software.
Controladores de base de datos y Python
Python, como cualquier otro lenguaje de programación, no puede comunicarse de forma nativa con una base de datos determinada. Requiere que se agreguen módulos adicionales para un servidor de base de datos específico. Desde el punto de vista de las mejores prácticas, es mejor utilizar un módulo de controlador de base de datos que sea específico para el servidor de base de datos elegido para el proyecto de software. Hacerlo garantiza que Python pueda acceder a todas las funciones del servidor de la base de datos, incluso si tiene el costo adicional de usar una sintaxis de programación específica para el módulo. Si bien se han realizado algunos intentos para crear módulos de controladores de bases de datos "universales" que puedan conectarse a varios servidores de bases de datos, a menudo esto se logra a expensas de perder el acceso a ciertas funciones de un servidor de bases de datos en particular.
¿Qué es SQL Express?
SQL Server ha sido la solución de servidor de base de datos para Windows durante décadas. Si bien está lo más lejos posible de una solución de servidor de base de datos gratuita, Microsoft proporciona una variante simplificada y de costo cero de SQL Server llamada SQL Express. SQL Express es una herramienta de aprendizaje ideal para principiantes, ya que admite la misma sintaxis de SQL que utiliza SQL Server. Tanto SQL Express como SQL Server usan una extensión personalizada de SQL llamada "Transact-SQL", también conocida como "T-SQL". Tanto SQL Express como SQL Server admiten el uso de cuentas de usuario de Windows y sistemas tradicionales de nombre de usuario y contraseña para la administración de acceso.
Python se comunica con SQL Express o SQL Server con un módulo llamado PyODBC . Tanto SQL Server como SQL Express son administrados por una aplicación de Windows separada y de costo cero llamada "Sistema de administración de SQL Server", conocido popularmente como "SSMS". En el momento de escribir este artículo, tanto SQL Express como SSMS son descargas independientes de Microsoft:
- Descarga de SSMS
- Descarga de SQL Express
Cómo configurar SQL Express para el desarrollo de Python
SQL Express, como SQL Server, admite dos tipos de autenticación. La primera es la autenticación basada en la cuenta de usuario de Windows de un usuario, también conocida como "Conexión de confianza". La segunda es la autenticación tradicional basada en nombre de usuario y contraseña que se implementa en lo que se denomina "Autenticación de modo mixto". La autenticación de modo mixto admite tanto la autenticación basada en cuentas de usuario de Windows como la autenticación basada en nombre de usuario y contraseña. No hay forma de admitir la autenticación basada en nombre de usuario y contraseña por sí sola en SQL Server o SQL Express.
Microsoft se ha alejado de la autenticación de modo mixto, ya que una de las principales ventajas de usar Trusted Connections es que las credenciales de la base de datos no necesitan almacenarse en el código de la aplicación. La demostración en este artículo tampoco lo usará.
NO copiar la cadena de conexión posterior a la instalación
Un punto de discordia para los desarrolladores de aplicaciones de nivel principiante es la confusión inicial que rodea las cadenas de conexión de SQL Server. Si uno está instalando SQL Express, el programa de instalación proporciona la cadena de conexión para la instancia de SQL Express creada después de la instalación. Lamentablemente, es probable que la cadena de conexión proporcionada no funcione con PyODBC . Si bien es tentador dejarse "arrullar" por una sensación de seguridad con este "obsequio", causará más problemas de los que vale la pena.
Figura 1:obtener la cadena de conexión del instalador de SQL Express
Tenga en cuenta que, en el momento de escribir este artículo, el programa de instalación de SQL Express también incluye un enlace para descargar el programa de instalación de SSMS.
Cómo crear una base de datos en SQL Express
Una vez que tanto SQL Express como SSMS están instalados, es hora de crear una base de datos básica con las restricciones de acceso adecuadas. La forma más fácil de iniciar SSMS es hacer clic en Inicio en Windows, escriba "ssms" en la barra de búsqueda, espere a que aparezca "Microsoft SQL Server Management Studio 18" en la esquina superior derecha y luego haga clic en Abrir enlace en el lado derecho del panel del menú Inicio:
Figura 2:inicio de SSMS
Al iniciar SSMS, aparece el siguiente cuadro de diálogo:
Figura 3:Diálogo de apertura de SSMS
Con la autenticación de Windows, no es necesario ingresar ninguna credencial. La cuenta de usuario de Windows en el que se instaló SQL Express tiene privilegios administrativos para la instancia de SQL Express. Simplemente haga clic en Conectar para proceder.
En el extremo izquierdo de la ventana de la aplicación SSMS , estará el Explorador de objetos . Para crear una nueva base de datos, haga clic derecho en Bases de datos y seleccione Crear base de datos del Contexto menú:
Figura 4:creación de una nueva base de datos:parte 1 de 2
Al hacer clic en Nueva base de datos... abrirá una nueva ventana de diálogo que permite ingresar los detalles de la nueva base de datos. Para esta demostración, la base de datos se llamará RazorDemo , como una especie de retroceso a un artículo anterior sobre el desarrollo de aplicaciones basadas en Razor en C#. Introduzca el nombre de la base de datos en el cuadro de texto junto a Nombre de la base de datos y luego haga clic en Aceptar botón en la parte inferior de la ventana de diálogo. Tenga en cuenta que, en la siguiente ilustración, las columnas para el Nombre lógico de los archivos se ampliaron ligeramente para que los Nombres lógicos completos de los archivos de la base de datos que se están creando fueron expuestos:
Figura 5:creación de una nueva base de datos:parte 2 de 2
La nueva base de datos aparecerá en el Explorador de objetos en Bases de datos carpeta:
Figura 6:la base de datos “RazorDemo” recién creada
Cómo crear tablas en SQL Express
Una base de datos relacional no es realmente útil sin tablas para almacenar los datos, y la forma más sencilla de crear esas tablas es usar código SQL. Tenga en cuenta que, si bien se podría usar el Asistente de creación de tablas para crear una tabla, usar código SQL es más rápido, más fácil y mucho más sencillo. Comience haciendo clic derecho en RazorDemo entrada de la base de datos, luego haga clic con el botón izquierdo en Nueva consulta opción en la ventana de contexto:
Figura 7:Abrir una nueva ventana de consulta
Aparecerá una ventana del editor de consultas similar a la siguiente a la derecha del Explorador de objetos :
Figura 8:la ventana del editor de consultas
El código de creación de la tabla se muestra en el listado a continuación:
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
Tenga en cuenta que al crear una ventana del editor de consultas from the database generalmente garantiza que la base de datos seleccionada será contra la cual se ejecutará el código, es una buena idea usar siempre explícitamente use la base de datos prevista al comienzo del código. El uso El comando selecciona explícitamente el nombre de la base de datos que le sigue.
Presionando F5 o haciendo clic en Ejecutar El botón ejecutará las declaraciones contra el RazorDemo base de datos. Si la ejecución tiene éxito, aparecerá un mensaje indicándolo en la sección “Mensajes recuadro a continuación:
Figura 9:Creación exitosa de tablas
Las tablas recién creadas y sus columnas se pueden ver en Object Explorer así como. Tenga en cuenta que, a veces, Actualizar Es posible que deba seleccionar la opción del menú contextual que aparece al hacer clic con el botón derecho en la base de datos para mostrar nuevos objetos dentro de una base de datos:
Figura 10:Actualización del Explorador de objetos
Figura 11:las nuevas tablas y sus columnas
En este punto, SSMS se puede cerrar de forma segura.
Tenga en cuenta que SSMS también funciona de la misma manera con cualquier base de datos de SQL Server. Siempre es una buena práctica guardar todo el código de creación de tablas sin importar qué servidor de base de datos se esté utilizando. Aunque SQL Server y SQL permiten la recuperación de dichos scripts, ambos también permiten el uso de cifrado en dichas declaraciones y, en esos casos, el código no se puede recuperar.
Python y SQL Express
Normalmente, aquí se necesitaría una discusión sobre la seguridad de SQL Server, pero desde Conexiones confiables se utilizará, siempre que el proceso en ejecución que ejecuta el código Python sea propiedad de un usuario de Windows que ya tiene acceso a una base de datos a la que se está accediendo, esa discusión no será necesaria. Tenga en cuenta que tanto SQL Server como SQL Express ofrecen personalizaciones muy sólidas relacionadas con la seguridad, pero están fuera del alcance de un artículo destinado a principiantes.
Tenga en cuenta que no pase por alto la seguridad adecuada de la base de datos para ninguna aplicación que se ejecute en un entorno de producción. Asegúrese de otorgar los mínimos privilegios posibles a la cuenta de usuario que accedería a una base de datos en un entorno de proyección.
La versión de Python utilizada para estos ejemplos de código es 3.10 y se instaló a través de Microsoft Store en Windows. La instalación de Python con este método agregará los ejecutables de Python y PIP3 a la ruta del sistema, por lo que no será necesario escribir las rutas completas a estos comandos en el Símbolo del sistema. ventanas Para la entrada de código, un buen editor de texto de costo cero es Notepad++.
Apertura de la ventana del símbolo del sistema
La mejor forma de ejecutar el código de Python es a través del Símbolo del sistema . Para acceder al Símbolo del sistema , haga clic en Inicio en Windows e ingrese cmd en la barra de búsqueda. Espere Símbolo del sistema que aparezca y luego haga clic en Abrir enlace en el lado derecho del Menú Inicio :
Figura 12:abrir un símbolo del sistema
Un Símbolo del sistema típico la ventana se ve así:
Figura 13:un símbolo del sistema típico
Cómo instalar PyODBC
PyODBC es el módulo de Python que permite a Python acceder tanto a SQL Server como a SQL Express. Tras la instalación de Python a través de Microsoft Store, PyODBC se puede agregar a Python a través del comando:
pip3 install pyodbc
Figura 14:instalación exitosa de PyODBC
Tenga en cuenta que si hay varias versiones de Python instaladas, por ejemplo, tanto Python 2 como Python 3, es posible que sea necesario agregar el prefijo pip3 comando con la ruta completa de Windows al comando para la versión apropiada de Python.
También tenga en cuenta que si solo está instalado Python 3, el pip3 el comando aún debe usarse sobre el pip más genérico comando, ya que esta es la convención adecuada.
Escribir código Python
Ahora que la base de datos está configurada y PyODBC están instalados, la base de datos se puede llenar. En el caso de una base de datos que catalogue artistas y álbumes, bastará con algunos nombres de bandas y álbumes generados aleatoriamente. También se incluye el código de Python para conectarse a la base de datos, pero las inserciones no (todavía):
# 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
Esto da el siguiente resultado:
Figura 15:nombres de bandas generados aleatoriamente
Tenga en cuenta el uso del cd comando para cambiar al directorio donde se guarda el código de Python. El PyODBC conectar() la función fallará si la cuenta de usuario de Windows que ha iniciado sesión actualmente no aparece como tener acceso en SQL Express. Esto solo es un problema si la base de datos se crea con una cuenta de usuario de Windows pero el código se ejecuta con una cuenta de usuario de Windows diferente .
La forma menos mala de INSERTAR datos en SQL y PyODBC
Muchos desarrolladores principiantes de Python se ven tentados a realizar llamadas a PyODBC llamadas a INSERTAR declaraciones en las siguientes secciones del código, y en el contexto de lo que se indicará a continuación, esta no es una mala idea:
Figura 16:la forma "casi" incorrecta de trabajar con una base de datos
La razón por la que se usan llamadas a PyODBC para realizar INSERT , SELECCIONES y otras funciones relacionadas con la base de datos, como ACTUALIZAR o ELIMINAR , dentro de los bucles puede ser malo porque hay una sobrecarga que viene con cada una de estas llamadas. Dentro de un ciclo que podría repetirse cientos de veces, miles de veces o incluso más, esto puede resultar en una cantidad significativa de tiempo (minutos o más) para ejecutar un script. Para las aplicaciones web que utilizan este enfoque, los problemas de rendimiento se agravan aún más, ya que muchos servidores web imponen límites máximos en la cantidad de tiempo que puede ejecutarse un script. Nunca, bajo ninguna circunstancia, pase las entradas creadas por el usuario directamente a una base de datos. Siempre verifique la entrada para asegurarse de que no rompa la funcionalidad de la base de datos o cause un problema de seguridad por medio de un ataque de inyección SQL.
Idealmente, uno querría usar los bucles anteriores para crear un lote de SQL (una lista de declaraciones) y luego tener PyODBC ejecutar en ese único lote, pero sería una muy mala idea si los datos no se desinfectan.
¿Por qué habría que desinfectar los datos? La razón se reduce a la seguridad, ya que nunca se puede confiar en la entrada del usuario. Desinfectar los datos significa representarlos de una manera que evite que se ejecute cualquier otra cosa que no sea la declaración SQL creada por el desarrollador del programa. Un usuario podría pasar una cadena construida maliciosamente que permitiría la ejecución de código SQL creado arbitrariamente. Esto se conoce como ataque de inyección SQL. Si bien los valores de datos que ingresan en un lote se pueden desinfectar, el proceso para hacerlo está más allá del alcance de un tutorial introductorio.
PyODBC proporciona un mecanismo para proteger la base de datos de los ataques de inyección SQL al desinfectar las entradas del usuario. Estos implican el uso de declaraciones parametrizadas , también conocido como declaraciones preparadas . La seguridad siempre debe ser una prioridad, incluso a costa de la velocidad u otras métricas de rendimiento.
La cuenta de usuario de Windows que tiene acceso a esta base de datos tiene privilegios de administrador del sistema de forma predeterminada. Esto significa que si se produce un ataque de inyección SQL, un usuario malintencionado puede obtener acceso a todos los datos de cada base de datos del servidor. En la práctica, ninguna cuenta con privilegios de administrador del sistema debería acceder a ninguna base de datos desde el código de Python.
La lista a continuación aumenta el primer ejemplo de código de Python usando PyODBC cursores para insertar los datos:
# 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
La siguiente consulta se puede ejecutar en SSMS para verificar la salida del código:
Figura 17:la inserción exitosa de los datos
Selección de datos en SQL Express y Python
Ahora que hay datos en la base de datos, sería bueno consultarlos. A continuación se muestra un script simple que acepta datos de usuario del teclado y los pasa a la base de datos a través de una consulta parametrizada:
# 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
Mismos resultados. Uno incluso incluye un ejemplo de un crudo ataque de inyección SQL:
Figura 18 – Resultados de la consulta. Anote el último valor de búsqueda.
Reflexiones finales sobre el desarrollo de bases de datos de Python
Realmente no hay límite para las aplicaciones impulsadas por SQL Server que se pueden desarrollar usando Python. Un desarrollador solo está limitado por el conocimiento de SQL y, con suerte, los conceptos fundamentales presentados en este artículo pueden guiar a un desarrollador de nivel principiante en la dirección correcta en términos de ampliar su comprensión de SQL y crear aplicaciones más complejas.
Este tutorial de programación de bases de datos de Python presentó los medios por los cuales SQL Express podría instalarse como un sustituto de desarrollo para SQL Server y mostró cómo Python 3 puede ampliarse para comunicarse correctamente con una instancia de base de datos de SQL Express en ese servidor. Este artículo también mostró cómo se debe usar SQL Server Management Studio para administrar cualquier base de datos de SQL Express o SQL Server. Yendo más allá, este artículo también se refirió a las precauciones básicas de seguridad y el uso de codificación eficiente con el fin de garantizar tiempos de ejecución razonables para las aplicaciones impulsadas por SQL Server.