We're pleased to announce the 12th release of the Microsoft Python Driver for SQL Server since GA: v1.12.0.
Want to try it?
pip install --upgrade mssql-python
What's new
Standalone mssql-python-odbc package for ODBC driver binaries
You may remember that we ran out of space to publish on PyPi a few releases ago. To prevent that from happening again, the ODBC driver binaries that mssql-python needs at runtime are now also published as a separate, pure-data companion package: mssql-python-odbc (import name mssql_python_odbc, currently pinned to 18.6.2).
mssql-python declares mssql-python-odbc==18.6.2 in install_requires, so pip install mssql-python transparently pulls the driver package alongside it. At import time, the native loader prefers the external mssql_python_odbc package when it is present, and falls back to the ODBC driver binaries still bundled inside the mssql-python wheel when it is not. Existing installations keep working with no code changes. The fallback is GIL-safe and Alpine/musl-safe.
Who benefits
- Users who want to keep driver binaries pinned or updated independently of the Python driver code.
- Redistributors who want a slimmer mssql-python wheel over time.
- Anyone who has hit duplicate-ownership issues from bundled ODBC files.
Bug fixes
Bulk copy now honors the connection timeout
cursor.bulkcopy() opens a separate connection through mssql_py_core, which previously defaulted to a hardcoded 15-second connect timeout with no way to override it from Python.
The cursor's query timeout (set via connect(timeout=X)) is now forwarded into mssql_py_core's connect_timeout when it is set. timeout=0 is preserved as "no override" and leaves mssql_py_core on its 15-second default. The cursor's timeout snapshot at the time of the bulkcopy() call is what is used, so later changes to the parent connection do not affect an in-flight bulk copy.
import mssql_python
# Give bulk copy 60 seconds to establish the second connection.
conn = mssql_python.connect(conn_str, timeout=60)
cursor = conn.cursor()
cursor.bulkcopy(rows, table="dbo.MyTable")
Who benefits
- Applications that call bulkcopy() against slow, throttled, or high-latency SQL Server endpoints (VPN, cross-region)
- Applications that need to fail fast with a shorter timeout.
Bulk copy into custom CLR UDT columns
cursor.bulkcopy() into a column whose type is a custom, assembly-registered CLR UDT (any UDT other than the built-in geography, geometry, or hierarchyid) previously failed with:
Protocol Error: Unsupported TDS type for bulk copy: 0xF0
The native core had no handler for the UDT (0xF0) type token when writing COLMETADATA. The Rust core now maps UDT columns to varbinary(max) on the wire and streams the supplied bytes as the UDT's serialized form (its IBinarySerialize payload), matching how pyodbc and python-tds load UDT columns. SQL Server materializes the UDT on insert.
More information
PyPI: https://pypi.org/project/mssql-python/1.12.0/
Release notes: https://github.com/microsoft/mssql-python/releases
README: https://github.com/microsoft/mssql-python#microsoft-python-driver-for-sql-server
Get involved
Bug reports, feature requests, and PRs are welcome on GitHub: https://github.com/microsoft/mssql-python