How to Extract Python Code from xlwings Lite Excel Files
Published: February 20, 2026
You can do this yourself or just copy paste the full post to your AI Coder (Claude Code , Cursor, Gemini etc) and it will do it for you in seconds.
Edit: Felix Zumstein pointed out a simpler way which I had missed - just click "Don't Trust" when the warning pops up and copy the code from the editor. Matter over. If you still want to extract the code without opening Excel at all, or want to understand where xlwings Lite stores its files, read on.
Purpose
Extract main.py and requirements.txt from an xlwings Lite .xlsx file without opening it in Excel. Useful for inspecting code before opening untrusted files, or for extracting scripts for version control.
How it works
- .xlsx files are ZIP archives containing XML files
- xlwings Lite stores Python code in: xl/webextensions/webextension1.xml
- The code is in a
<we:property name="main.py" value="...">XML attribute - The value is JSON-encoded (escaped quotes, \n for newlines)
- json.loads() decodes it back to clean Python
What gets extracted
- main.py - The Python script (the actual code)
- requirements.txt - Package dependencies
- pyodideVersion - Pyodide runtime version
- addinVersion - xlwings Lite add-in version
Extraction script
Save as extract_xlwings_code.py or run inline:
import zipfile
import xml.etree.ElementTree as ET
import json
import sys
import os
def extract_xlwings_code(xlsx_path, output_dir=None):
"""Extract main.py and requirements.txt from an xlwings Lite Excel file."""
if output_dir is None:
output_dir = os.path.dirname(xlsx_path)
with zipfile.ZipFile(xlsx_path, 'r') as z:
with z.open('xl/webextensions/webextension1.xml') as f:
tree = ET.parse(f)
root = tree.getroot()
ns = {'we': 'http://schemas.microsoft.com/office/webextensions/webextension/2010/11'}
for prop in root.findall('.//we:property', ns):
name = prop.get('name')
value = prop.get('value', '')
if name == 'main.py':
code = json.loads(value)
out_path = os.path.join(output_dir, 'extracted_main.py')
with open(out_path, 'w', encoding='utf-8') as out:
out.write(code)
lines = code.count('\n') + 1
print(f'main.py: {lines} lines, {len(code)} chars -> {out_path}')
elif name == 'requirements.txt':
req = json.loads(value)
out_path = os.path.join(output_dir, 'extracted_requirements.txt')
with open(out_path, 'w', encoding='utf-8') as out:
out.write(req)
print(f'requirements.txt -> {out_path}')
print(f' Packages: {req}')
elif name in ('pyodideVersion', 'addinVersion'):
print(f'{name}: {json.loads(value)}')
if __name__ == '__main__':
if len(sys.argv) < 2:
print('Usage: py extract_xlwings_code.py <path_to_xlsx> [output_dir]')
sys.exit(1)
xlsx = sys.argv[1]
out = sys.argv[2] if len(sys.argv) > 2 else None
extract_xlwings_code(xlsx, out)
Quick one-liner
From the command line:
py -c "
import zipfile, xml.etree.ElementTree as ET, json, sys
z=zipfile.ZipFile(sys.argv[1]); t=ET.parse(z.open('xl/webextensions/webextension1.xml'))
ns={'we':'http://schemas.microsoft.com/office/webextensions/webextension/2010/11'}
[print(json.loads(p.get('value',''))) for p in t.getroot().findall('.//we:property',ns) if p.get('name')=='main.py']
" "C:\path\to\file.xlsx"
Example usage
Full extraction:
py extract_xlwings_code.py "C:\path\to\your\xlwings_lite_file.xlsx"
Extract to specific directory:
py extract_xlwings_code.py "C:\path\to\file.xlsx" "C:\output\dir"
Notes
- xlwings Lite stores everything as plain text in XML - fully inspectable
- No Excel installation needed - pure Python, standard library only
- Works on Windows, macOS, Linux
xlwings Lite official site: lite.xlwings.org