Python Microsoft Fabric - Sending and receiving files
Pick up files that were dropped for you, load them into tables and write exports for the Fabric team.
Two kinds of files live in the lakehouse's Files section - files another system drops for you, and exports you write for the Fabric team. This page loads the first kind into a table and writes the second.
OneLake is the storage behind every lakehouse - the Files section you see in the lakehouse explorer is a folder in it, and the connection reads and writes there directly.
File paths
Every file path starts with the lakehouse and continues into its Files section, for example Operations.Lakehouse/Files/incoming/payments-2026-03.csv. The lakehouse ID works in place of Operations.Lakehouse too, which is what the code below uses, since it already has the ID.
The file that was dropped
Another system drops one CSV file a month in Files/incoming, with the same columns the invoices table has:
The service lists the folder, loads each file into the table and deletes it once the load is done, so a file is never loaded twice.
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class LoadPaymentFiles(Service):
def handle(self):
workspace_id = '11111111-2222-3333-4444-555555555555'
lakehouse_id = '66666666-7777-8888-9999-000000000000'
conn = self.microsoft.fabric['My Fabric']
loaded = []
# Everything currently in the incoming folder ..
listing = conn.onelake_list(workspace_id, f'{lakehouse_id}/Files/incoming')
for path in listing['paths']:
# .. skipping subfolders ..
if path['isDirectory']:
continue
# .. the listing gives the full path, the load needs it relative to the lakehouse ..
full_path = path['name']
_, relative_path = full_path.split('/', 1)
# .. load it into the table, adding to what is there ..
location = conn.load_table(workspace_id, lakehouse_id, 'invoices', relative_path, mode='Append')
conn.wait_for_operation(location)
# .. and remove the file so the next run does not see it again.
conn.onelake_delete(workspace_id, full_path)
loaded.append(relative_path)
self.response.payload = {'loaded': loaded}
After the run, the folder is empty and the table has a new row for each line of the file:
The monthly export
The second service writes a monthly CSV file to Files/exports, where the Fabric team opens it. The rows come from another system, and the service turns them into CSV and writes the file.
# -*- coding: utf-8 -*-
# stdlib
import csv
import io
# Zato
from zato.server.service import Service
class WriteInvoiceExport(Service):
def handle(self):
workspace_id = '11111111-2222-3333-4444-555555555555'
lakehouse_id = '66666666-7777-8888-9999-000000000000'
month = '2026-03'
conn = self.microsoft.fabric['My Fabric']
# The month's totals from the system that owns them, one dict per location.
rows = [
{'location': 'Riverside', 'invoiced': 2895.50},
{'location': 'Oak Hill', 'invoiced': 1840.00},
{'location': 'Maple Grove', 'invoiced': 415.75},
]
# Turn the rows into CSV text ..
buffer = io.StringIO()
writer = csv.DictWriter(buffer, fieldnames=['location', 'invoiced'])
writer.writeheader()
writer.writerows(rows)
text = buffer.getvalue()
data = text.encode('utf-8')
# .. and write the file where the Fabric team looks for it.
file_path = f'{lakehouse_id}/Files/exports/invoices-{month}.csv'
conn.onelake_write(workspace_id, file_path, data)
self.response.payload = {'file': file_path, 'rows': len(rows)}
The service writes Files/exports/invoices-2026-03.csv:
onelake_write creates the file or replaces it if it exists, so running the export twice for the same month leaves one file.
See also
| Page | What it covers |
|---|---|
| Loading data into tables | Appending and replacing tables from rows a service already holds |
| Sending reports on a schedule | The same CSV, delivered by SFTP and email instead |
| Files | onelake_list, onelake_read, onelake_write and onelake_delete in detail |