Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Por padrão, o driver mssql-python converte tipos de dados Microsoft SQL para tipos Python apropriados (veja Mapeamentos de tipos de dados). O sistema de conversor de saída permite que você substitua esse comportamento para tipos SQL específicos, habilitando:
- Transformações de tipos personalizadas (por exemplo, dinheiro para float em vez de decimal)
- Integração com bibliotecas de terceiros (por exemplo, dados espaciais para objetos Shapely)
- Formatação específica para negócios (por exemplo, datas em formatos personalizados de cadeia de caracteres)
Registrar conversores de saída
Use add_output_converter() para registrar uma função de conversor. A chave é ou um tipo Python que corresponde ao type_code em cursor.description, ou um código inteiro ODBC SQL, como mssql_python.SQL_DECIMAL:
import mssql_python
from datetime import datetime
def my_datetime_converter(value):
"""Convert datetime to a custom display string."""
if value is None:
return None
return value.strftime("%B %d, %Y at %I:%M %p")
conn = mssql_python.connect(connection_string)
conn.add_output_converter(datetime, my_datetime_converter)
cursor = conn.cursor()
cursor.execute("SELECT CAST('2026-07-16T10:30:00' AS DATETIME2)")
print(cursor.fetchval()) # July 16, 2026 at 10:30 AM
Escolha entre uma chave de tipo Python e uma chave de código de tipo SQL
As duas formas-chave diferem na precisão com que selecionam as colunas:
Uma chave de tipo Python é aplicável a cada tipo SQL que mapeia para esse tipo Python. Registrar um conversor em
Decimaltransforma colunas decimal, numeric, money e smallmoney.Uma chave de código de tipo SQL inteiro corresponde ao código ODBC que a coluna reporta, que é mais estreito, mas nem sempre é um único tipo SQL.
SQL_NUMERICtransforma apenas colunas numéricas .SQL_DECIMALTransforma as colunas decimal, dinheiro e smallmoney , porque as três reportam esse mesmo código.
Use uma chave inteira quando uma chave de tipo Python for mais abrangente do que o desejado ou quando estiver portando código do pyodbc, que usa chaves inteiras. Use uma chave de tipo Python quando quiser que um conversor cubra toda uma família de tipos SQL.
import mssql_python
def tag_decimal(value):
return f"D:{value}"
conn.add_output_converter(mssql_python.SQL_DECIMAL, tag_decimal)
cursor.execute("""
SELECT CAST(12.34 AS decimal(10,2)),
CAST(56.78 AS numeric(10,2)),
CAST(90.12 AS money)
""")
print(cursor.fetchone()) # ('D:12.34', Decimal('56.78'), 'D:90.1200')
Ordem de resolução do conversor
Para cada coluna, o driver seleciona no máximo um conversor, nesta ordem:
O conversor se registrou para o código inteiro ODBC SQL da coluna.
O conversor registrado para o tipo Python em
cursor.description.O conversor foi registrado para
SQL_WVARCHAR, mas somente quando o tipo Python da coluna éstroubytes.
Assinatura de função conversora
Quando você registra um conversor usando uma chave de tipo do Python, o tipo passado para add_output_converter() deve corresponder a um dos seguintes tipos do Python. A coluna Conversor recebe mostra o que o driver passa para sua função:
cursor.description type_code |
Conversor recebe | Tipos SQL da Microsoft |
|---|---|---|
int |
int |
tinyint, smallint, int, bigint |
float |
float |
real, float |
decimal.Decimal |
Decimal |
decimal, numeric, money, smallmoney |
str |
bytes (codificado em UTF-16LE) |
char, varchar, nchar, nvarchar, xml |
datetime.datetime |
datetime |
datetime, datetime2, smalldatetime |
datetime.date |
date |
date |
bytes |
bytes |
varbinary, binary, geography, geometry |
bool |
bool |
bit |
Note
Conversores do tipo cadeia de caracteres (chave str) recebem bytes bruto na codificação UTF-16LE, não cadeias de caracteres Python decodificadas. Todos os outros tipos recebem o objeto Python já convertido.
from decimal import Decimal
def decimal_converter(value: Decimal | None) -> float | None:
if value is None:
return None
# value is a Decimal object for numeric/money types
return float(value)
Gerenciar conversores
Use esses métodos para inspecionar ou remover conversores já registrados em uma conexão.
Obter conversor existente
Recupere a função conversora atualmente registrada para um tipo:
converter = conn.get_output_converter(str)
if converter:
print(f"Converter registered: {converter}")
else:
print("Using default conversion")
Remova um conversor
Desregistre um conversor para que o driver volte à conversão padrão para aquele tipo:
conn.remove_output_converter(str)
# str columns now use default conversion
Limpe todos os conversores
Resete todos os conversores registrados para usar os mapeamentos de tipos padrão do Microsoft SQL:
conn.clear_output_converters()
# All types now use default conversion
Padrões comuns de conversores
Esses exemplos mostram as funções de conversor mais frequentemente necessárias.
Converta VARCHAR em maiúsculas
Conversores do tipo string recebem bytes brutos na codificação UTF-16LE:
def uppercase_converter(value):
if value is None:
return None
return value.decode('utf-16-le').upper()
conn.add_output_converter(str, uppercase_converter)
cursor = conn.cursor()
cursor.execute("SELECT 'hello world'")
print(cursor.fetchval()) # HELLO WORLD
Converter dinheiro em float
Por padrão, o driver retorna os tipos DECIMAL/NUMÉRICO como decimal.Decimal. Converter para float:
from decimal import Decimal
def money_to_float(value):
if value is None:
return None
return float(value)
conn.add_output_converter(Decimal, money_to_float)
cursor = conn.cursor()
cursor.execute("SELECT CAST(19.99 AS MONEY)")
result = cursor.fetchval()
print(type(result)) # <class 'float'>
Analisar dados JSON
Microsoft SQL Server pode armazenar JSON como texto. Análise automática para objetos Python:
import json
def json_converter(value):
if value is None:
return None
text = value.decode('utf-16-le')
try:
return json.loads(text)
except json.JSONDecodeError:
return text # Return as string if not valid JSON
conn.add_output_converter(str, json_converter)
cursor = conn.cursor()
cursor.execute("SELECT '{\"name\": \"Widget\", \"price\": 19.99}'")
data = cursor.fetchval()
print(data['name']) # Widget
Cuidado
Este exemplo converte TODOS os valores das strings (nvarchar, varchar, xml). A análise de JSON é feita em cada coluna de texto. Na prática, aplique a análise de JSON de forma seletiva, em vez de usá-la como um conversor genérico.
Formatação personalizada de data e hora
Converter datetime para formato de cadeia de caracteres ISO:
from datetime import datetime
def datetime_to_iso(value):
if value is None:
return None
return value.isoformat()
conn.add_output_converter(datetime, datetime_to_iso)
cursor = conn.cursor()
cursor.execute("SELECT TOP 1 ModifiedDate FROM Production.Product")
print(cursor.fetchval()) # 2014-02-08T10:01:36.827000
Considerações de segurança
Cuidado
Quando você registra um conversor de saída, a função que você fornece é executada para cada valor correspondente no banco de dados.
- Registre apenas conversores provenientes de código confiável.
- Nunca aceite funções de conversor a partir da entrada do usuário.
- Conversores maliciosos podem executar código arbitrário ou vazar dados.
# DANGEROUS - never do this
def unsafe_example(user_converter_code):
converter_func = eval(user_converter_code) # Security risk!
conn.add_output_converter(str, converter_func)
Exemplo: Integração de dados espaciais
Integre dados espaciais com a biblioteca Shapely:
from shapely import wkb
def geometry_converter(value):
"""Convert WKB binary to Shapely geometry object."""
if value is None:
return None
return wkb.loads(value)
conn.add_output_converter(bytes, geometry_converter)
# Query must use STAsBinary() to get standard WKB format
cursor = conn.cursor()
cursor.execute(
"SELECT SpatialLocation.STAsBinary() FROM Person.Address "
"WHERE SpatialLocation IS NOT NULL AND City = 'Seattle'"
)
for row in cursor:
shape = row[0]
print(f"Point: ({shape.x:.4f}, {shape.y:.4f})")
Note
Registrar um bytes conversor afeta TODAS as colunas binárias (varbinária, geográfica, geométrica). Use clear_output_converters() após consultas espaciais se também consultar dados binários não espaciais.
Exemplo: Formatação personalizada de linha
Crie um conversor de classe de dados:
from dataclasses import dataclass
@dataclass
class Product:
id: int
name: str
price: float
def fetch_products_as_dataclass(cursor):
"""Convert rows to Product dataclass instances."""
cursor.execute(
"SELECT ProductID, Name, ListPrice FROM Production.Product "
"WHERE ListPrice > 0"
)
results = []
for row in cursor:
results.append(Product(
id=row.ProductID,
name=row.Name,
price=float(row.ListPrice)
))
return results
products = fetch_products_as_dataclass(cursor)
for p in products[:5]:
print(f"{p.name}: ${p.price:.2f}")
Escopo e vida útil do conversor
- Escopo de conexão: o driver registra conversores por conexão, não globalmente.
- Persistente: Os conversores permanecem ativos até que você os remova ou feche a conexão.
- Não herdado: Novas conexões não herdam conversores de outras conexões.
conn1 = mssql_python.connect(connection_string)
conn1.add_output_converter(str, uppercase_converter)
conn2 = mssql_python.connect(connection_string)
# conn2 does NOT have the converter registered
Considerações sobre desempenho
- O driver chama conversores para cada valor do tipo registrado.
- Mantenha as funções do conversor eficientes.
- Para consultas de alto volume, considere se a conversão é necessária.
- Analise o desempenho para verificar se os conversores afetam a taxa de transferência.
import time
def slow_converter(value):
time.sleep(1) # Avoid time consuming routines like this - adds 1 second for each value processed!
return str(value) if value else None