Repository navigation
bulkcopy_arrow() / bulkcopy()` broken in 1.16.0 #855
Description
Title
bulkcopy_arrow() / bulkcopy() broken in 1.16.0: AttributeError: module 'mssql_py_core' has no attribute 'PyCoreConnection'
Description
After upgrading from 1.15.0 to 1.16.0, any call to cursor.bulkcopy_arrow(...) (and presumably cursor.bulkcopy(...), which shares the same pycore connection path) fails immediately with:
AttributeError: module 'mssql_py_core' has no attribute 'PyCoreConnection'
Full traceback:
File ".../site-packages/mssql_python/cursor.py", line 3764, in bulkcopy_arrow
pycore_connection = mssql_py_core.PyCoreConnection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'mssql_py_core' has no attribute 'PyCoreConnection'
This reproduces on a clean pip install mssql-python==1.16.0 with no other code changes — the exact same script works correctly against 1.15.0.
Root cause
This looks like a packaging regression from the 1.16.0 change that split the Rust runtime out into a separate version-matched mssql-python-rs package (per the 1.16.0 release notes).
On Windows, after pip install mssql-python==1.16.0, the compiled extension lands at:
site-packages/mssql_py_core/mssql_py_core.pyd
There is no __init__.py inside site-packages/mssql_py_core/. As a result, import mssql_py_core resolves to an empty implicit namespace package (PEP 420) rather than loading the compiled extension — so mssql_py_core.PyCoreConnection doesn't exist at that path.
The compiled extension itself is fine and fully functional — it just needs to be imported one level deeper:
import mssql_py_core.mssql_py_core as core
print([a for a in dir(core) if "Connection" in a])
# -> ['PyAsyncConnection', 'PyCoreConnection']But mssql_python/cursor.py's bulkcopy_arrow (and likely bulkcopy) does a plain top-level import mssql_py_core and then calls mssql_py_core.PyCoreConnection(...) directly, which hits the empty namespace package instead of the real module.
Likely fix: either (a) add an __init__.py to the mssql_py_core package in the mssql-python-rs wheel that re-exports from the nested mssql_py_core.mssql_py_core extension module, or (b) update mssql-python's internal imports to reference mssql_py_core.mssql_py_core explicitly.
Environment
mssql-python: 1.16.0 (regression; works correctly on 1.15.0)mssql-python-rs: 0.3.0mssql-python-odbc: 18.6.2.2- Python: 3.11.0
- OS: Windows 10/11 (
Windows-10-10.0.26200-SP0), x86_64 - Install method:
pip install mssql-python==1.16.0(clean upgrade from 1.15.0 in an existing venv)
Reproduction steps
pip install mssql-python==1.16.0
python -c "
import mssql_python
cn = mssql_python.connect('SERVER=...;DATABASE=...;Trusted_Connection=yes;')
cur = cn.cursor()
cur.bulkcopy_arrow('some_table', some_pyarrow_record_batch_reader)
"Minimal repro of the underlying import issue (no SQL Server connection needed):
import mssql_py_core
print(mssql_py_core.__file__) # None -- confirms empty namespace package
print(hasattr(mssql_py_core, "PyCoreConnection")) # False
import mssql_py_core.mssql_py_core as core
print(core.__file__) # points to the real .pyd
print(hasattr(core, "PyCoreConnection")) # TrueExpected behavior
import mssql_py_core should expose PyCoreConnection (and PyAsyncConnection) at the top level, as it presumably did before the 1.16.0 packaging split, so bulkcopy_arrow()/bulkcopy() work without modification.
Actual behavior
bulkcopy_arrow() / bulkcopy() are completely broken on 1.16.0 for Windows installs via pip, with no workaround short of pinning back to 1.15.0.
Impact
This blocks all bulk-copy / Arrow bulk-load workflows on 1.16.0. We've rolled back to 1.15.0 in the meantime.
Activity
github-actions commentedon Oct 21, 2026
Hi sanjaywa, thank you for opening this issue!
Our team will review it shortly. We aim to triage all new issues within 24-48 hours and get back to you.
If you have additional information to share, please feel free to update the issue.
Thank you for your patience!