Leveraging SQL Server File Streaming with Python

My goal is to utilize SQL Server 2017 filestream in a Python environment. Since I rely heavily on SQLAlchemy for functionality, I am seeking a way to integrate filestream support into my workflow. Despite searching, I have not come across any implementations within SQLAlchemy or other libraries (potentially missed something, so please direct me to a proven solution).

I opted to work with the DLL approach based on https://github.com/VisionMark/django-mssql-filestream/blob/master/sql_filestream/win32_streaming_api.py. However, when attempting to call OpenSqlFilestream, it fails and returns -1 instead of a file handle. Troubleshooting this issue has left me unsure of what's causing it or how to resolve it.

from ctypes import c_char, sizeof, windll
from sqlalchemy import create_engine
from sqlalchemy.orm import session_maker
import msvcrt
import os

msodbcsql = windll.LoadLibrary("C:\Windows\System32\msodbcsql17.dll") 

engine = create_engine("mssql+pyodbc://user:pass@test/test?TrustedConnection=yes+driver=ODBC Driver+17+for+SQL+Server")
maker = session_maker(bind=engine)
session = session_maker()
## first query should begind transaction
path = session.execute("SELECT file_stream.PathName() FROM test_filetable").fetchall()[0][0]
## this returns str like "\\\\test\\*"
context = session.execute("SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()").fetchall()[0][0]
## returns bytes

_context = (c_char*len(context)).from_buffer_copy(context)

## This call fails
handle = msodbcsql.OpenSqlFilestream(
        path, # FilestreamPath
        0, # DesiredAccess
        0, # OpenOptions
        _context, # FilestreamTransactionContext
        sizeof(_context), # FilestreamTransactionContextLength
        0 # AllocationSize
    )
## this returns -1 instead of handle

## Never reached, but this should create usable file
desc = msvcrt.open_osfhandle(fsHandle, os.O_RDONLY)
_file = os.fdopen(desc, 'r')

All queries seem to be functioning correctly and producing expected outputs.

How can I establish filestream access to a file on SQL Server 2017 from Python (3.7)?

Edit: The objects I'm handling are gigabytes in size, and stream access is all that's required during processing.

Answer №1

It seems like the issue you are facing could be attributed to

  1. The complexity of a SQLAlchemy Session, which is more than just a basic DB API Connection, and/or
  2. The mismatch in transaction context when using OpenSqlFilestream

Here's an example that I have successfully tested with CPython 3.7.2 and pythonnet 2.4.0:

import clr
clr.AddReference("System.Data")
from System.Data import IsolationLevel
from System.Data.SqlClient import SqlCommand, SqlConnection
from System.Data.SqlTypes import SqlFileStream
from System.IO import File, FileAccess, FileOptions

# Code adapted from a C# example at
# https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/filestream-data
connection_string = r"Data Source=(local)\SQLEXPRESS;Initial Catalog=myDB;Integrated Security=True"
con = SqlConnection(connection_string)
con.Open()
sql = """\
SELECT Photo.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT()
FROM employees WHERE EmployeeID = 1"""
cmd = SqlCommand(sql, con)
tran = con.BeginTransaction(IsolationLevel.ReadCommitted)
cmd.Transaction = tran
rdr = cmd.ExecuteReader()
rdr.Read()
path = rdr.GetString(0)
transaction_context = rdr.GetSqlBytes(1).Buffer
rdr.Close()
allocation_size = 0
input_stream = SqlFileStream(path, transaction_context,
        FileAccess.Read, FileOptions.SequentialScan, allocation_size)
output_stream = File.Create(r"C:\Users\Gord\Desktop\photo.bmp")
input_stream.CopyTo(output_stream)
output_stream.Close()
input_stream.Close()
tran.Commit()
con.Close()

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Analyze a text document containing columns arranged neatly using white spaces

One of the challenges I'm facing is parsing a text file with entries aligned in columns using multiple white spaces. Here's how the text appears: Blah blah, blah bao 123456 hello, hello, hello miao 299292929 ...

I have come across an issue with an additional set of "[]" in the json data I generated. Is there a way to eliminate them from the file

I use json to print out the data obtained from my database, but I am facing an issue where there is an unwanted extra "[]" character being printed. How can I get rid of this or fix it? sql = """select array_to_json(array_agg(row_to_json(a))) ...

Python 3: Organizing a Complex Application

Looking for guidance on how to effectively organize a large Python application that requires multiple files in different subdirectories for optimal project organization. All the resources I've come across discuss packages, which seem similar to librar ...

When attempting to click a button using Python, an error may be encountered known as TimeoutException in the selenium module

I am encountering an error while using the Selenium package to automate button clicks on a website. The specific error message is: selenium.common.exceptions.TimeoutException: Message: Below is the code snippet that I'm attempting to execute: impor ...

Getting a class object back from Oct2Py

I'm attempting to execute a simple MATLAB script that defines a class and returns that class object to Python. I have limited experience with MATLAB and am new to Oct2Py, so I may not fully understand the process. Any assistance would be greatly value ...

What is the method for sorting a Python list both numerically in descending order and alphabetically in ascending order simultaneously?

My goal is to arrange a list that contains tuples with a word and a number. my_list = [('hello',25), ('hell',4), ('bell',4)] I am looking for a way to sort this list (maybe using lambda) in order to achieve the following: [ ...

What is the method for inserting a clickable link at the top of every page in a Python PDF document?

We are currently in the process of uploading scanned and OCRed documents onto a website and require a way to insert a link on each page. This link will direct users who come across the pages through a search engine to the main index containing related docu ...

What is the best way to swap out characters according to the user's input?

new = ['|<', '@', '1', '3', '7', '0', '8', '\/'] old = ['K', 'A', 'L', 'E', 'T', 'O', 'B', 'V ...

What is the best way to obtain just the name and phone number information?

Looking to extract the name and contact number from a div that can contain one, two, or three spans. The requirements are: Extract name and contact number only when available. If contact number is present but name is missing, assign 'N/A' to th ...

Tips for changing window size using Selenium WebDriver and Python

Is there a way to resize the browser window (e.g. chrome window) using selenium webdriver with python? A related question can be found in reference 1, but it does not offer a satisfactory solution and only adds confusion. The answer provided here address ...

When attempting to load a new page from an iframe by clicking a button, the selenium driver fails to retrieve the page source of the newly loaded page

I am currently working on creating a WebDriver using selenium with Python. I have successfully switched to an iFrame using driver.switch_to.frame(driver.find_element(by=By.CSS_SELECTOR, value='iframe[id="iframe_id"]')). Within the iFram ...

I'm faced with a predicament in Python where I need to split a portion of text using the line-ending characters at the end of each

In my program, I am working on analyzing XML files and one of the tasks is to split the data into sentences. However, I have encountered an issue where my line end characters are missing. I need to include them in order to add annotations with XML tags at ...

Exporting Python Pandas Data Frame to an HTML file

I'm attempting to save a Python Pandas Data Frame as an HTML page. I also want to ensure that the table can be filtered by the value of any column when saved as an HTML table. Do you have any suggestions on how to accomplish this? Ultimately, I want t ...

When Selenium is not in headless mode, it cannot capture a screenshot of the entire website

Disclaimer: Although there is a similar question already out there, none of the answers provided worked for a headless browser. Therefore, I have decided to create a more detailed version addressing this specific issue (the original question I referred to ...

Comparing time across different time zones using Python

I need to schedule daily emails for users at 7am in their respective time zones. For instance, User 1 is in the America/Los_Angeles time zone, while Customer 2 is in America/New_York and would receive the email at 7am their local time, but it would be 4am ...

Struggling to showcase information from a JSON file within an embed on a webpage

I am struggling to display the data from my JSON file in an embed. I need assistance with finding a solution for this issue. Here is the content of the JSON file: { "Slims Mod Bot": { "Felix\u2122": 2, "Dus ...

Tips on resolving the issue of an element being unclickable at a particular point in Selenium when using

I'm currently testing a script that involves navigating through approximately 200 pages. Each page features an edit button that needs to be clicked on. While I successfully click the button on about half of the pages, the other half presents an error ...

Transmit a lexicon containing values encapsulated within a roster to an AJAX solicitation, endeavoring to dissect it at the receiving

My goal is to send a dictionary that looks like this (values in a list): datax = { "name": ["bhanu", "sivanagulu","daniel"], "department": ["HR", "IT", "FI"]} In ...

Does the list automatically remove its values once the session ends?

I have been successfully adding some answers to a list, which is great. However, I am concerned about what happens when the session ends. Will these answers be removed from the list? The problem arises when I rerun the code and find that the list appears ...

Encountering the error message "Failed to load resource: the server responded with a status of 500 (Internal Server Error)" while using Django and Vue on my website

While working on my project that combines Vue and Django, I encountered a persistent error message when running the code: "Failed to load resource: the server responded with a status of 500 (Internal Server Error) 127.0.0.1:8000/api/v1/products/winter/yel ...