Of course! Let's break down how to work with Subversion (SVN) repositories in Python.

The most common and robust way to do this is by using a dedicated library that interacts with the SVN command-line client (svn) on your system. This is generally more reliable than trying to implement the SVN protocol from scratch.
Here’s a complete guide covering the best practices, code examples, and troubleshooting.
The Recommended Approach: Using the pysvn Library
The most popular and feature-rich library for SVN in Python is pysvn. It acts as a wrapper around the native svn command-line tools, giving you fine-grained control over SVN operations.
Step 1: Install Prerequisites
Before installing pysvn, you must have the Subversion command-line client installed on your system.

- On Debian/Ubuntu:
sudo apt-get update sudo apt-get install subversion
- On macOS (using Homebrew):
brew install subversion
- On Windows:
- Download the latest binaries from the official Subversion website.
- Run the installer. Make sure to check the option to add
svnto your system's PATH during installation. - Verify the installation by opening a new command prompt and typing
svn --version.
Step 2: Install pysvn
pysvn is not available on PyPI, so you can't install it with a simple pip install pysvn. You need to use its specific installer.
- Go to the pysvn downloads page.
- Download the appropriate installer for your Python version and operating system (e.g.,
pysvn-1.9.7-python-3.8-win32.exeorpysvn-1.9.7-python-3.8.tar.gz). - Run the installer or extract the archive. The installer will automatically integrate
pysvnwith your Python installation.
Step 3: Basic Code Examples
Now you can import pysvn in your Python scripts. The convention is to import it as pysvn to avoid name conflicts.
import pysvn
# --- 1. Basic Client Setup ---
# Create a client object. This is your main entry point for all SVN operations.
client = pysvn.Client()
# --- 2. Checking Out a Repository ---
# This is equivalent to running `svn checkout <repo_url> <local_path>`
print("Checking out repository...")
try:
client.checkout(
"https://svn.apache.org/repos/asf/subversion/trunk/notes", # SVN Repository URL
"./my_svn_checkout" # Local directory to create
)
print("Checkout successful!")
except pysvn.ClientError as e:
print(f"Checkout failed: {e}")
# --- 3. Getting Information About a Local Working Copy ---
# This is equivalent to running `svn info`
print("\nGetting info for the local checkout...")
try:
info = client.info("./my_svn_checkout")
if info:
print(f"Repository Root: {info['repos_root_url']}")
print(f"URL: {info['url']}")
print(f"Revision: {info['commit_revision']}")
print(f"Last Author: {info['author']}")
print(f"Last Changed: {info['date']}")
except pysvn.ClientError as e:
print(f"Info command failed: {e}")
# --- 4. Getting Log Entries ---
# This is equivalent to running `svn log -l <number_of_entries>`
print("\nGetting log entries...")
try:
log_entries = client.log("./my_svn_checkout", limit=5)
for entry in log_entries:
print(f"Revision {entry.revision.number} by {entry.author} on {entry.date}")
print(f" Message: {entry.message}")
print("-" * 20)
except pysvn.ClientError as e:
print(f"Log command failed: {e}")
# --- 5. Adding a New File and Committing ---
import os
# Create a new file in the working copy
new_file_path = "./my_svn_checkout/new_file.txt"
with open(new_file_path, "w") as f:
f.write("This is a new file added via Python script.")
print(f"\nAdding new file: {new_file_path}")
# Add the file to SVN's attention
client.add(new_file_path)
# Commit the change
print("Committing the change...")
try:
client.checkin(
[new_file_path], # List of items to commit
"Adding a new file via pysvn" # Commit log message
)
print("Commit successful!")
except pysvn.ClientError as e:
print(f"Commit failed: {e}")
# --- 6. Updating the Working Copy ---
print("\nUpdating the working copy...")
try:
# client.update() returns a list of all changed items
updated_items = client.update("./my_svn_checkout")
if updated_items:
print(f"Updated {len(updated_items)} items.")
else:
print("Working copy is already up to date.")
except pysvn.ClientError as e:
print(f"Update failed: {e}")
Alternative Approach: Running svn Commands with subprocess
If you don't want to install pysvn or just need to perform simple, one-off SVN commands, you can use Python's built-in subprocess module to execute the svn command-line tool directly.
This method is less integrated but can be quicker for simple scripts.

import subprocess
import os
def run_svn_command(command_args, working_dir="."):
"""
Runs a command-line svn command and returns its output.
Raises an exception on error.
"""
print(f"Running command: svn {' '.join(command_args)}")
try:
# Use check_output to run the command and capture stdout
# The `svn` command usually returns non-zero on error, which check_output will raise
output = subprocess.check_output(
["svn"] + command_args,
cwd=working_dir,
stderr=subprocess.STDOUT, # Capture stderr too
text=True
)
return output.strip()
except subprocess.CalledProcessError as e:
print(f"SVN command failed with return code {e.returncode}")
print(f"Output:\n{e.output}")
raise
# --- Example Usage ---
# 1. Get info
print("--- Using subprocess ---")
try:
info_output = run_svn_command(["info", "./my_svn_checkout"])
print("\nSVN Info Output:")
print(info_output)
except Exception as e:
print(f"Could not get info: {e}")
# 2. Get log
try:
log_output = run_svn_command(["log", "-l", "5", "./my_svn_checkout"])
print("\nSVN Log Output:")
print(log_output)
except Exception as e:
print(f"Could not get log: {e}")
# 3. Add and commit (more complex, requires careful parsing)
# This is where pysvn is much easier and safer.
new_file_path_sub = "./my_svn_checkout/subprocess_file.txt"
with open(new_file_path_sub, "w") as f:
f.write("This file was managed using subprocess.")
try:
# Add the file
run_svn_command(["add", new_file_path_sub])
# Commit the file
# Note: This is tricky. You might need to pipe the commit message to 'svn'
# or use a temporary file. The command is different on OS X/Linux vs. Windows.
# For simplicity, we'll use the --message flag.
commit_output = run_svn_command([
"commit",
new_file_path_sub,
"--message", "Adding a file via subprocess"
])
print("\nSVN Commit Output:")
print(commit_output)
except Exception as e:
print(f"Could not add/commit: {e}")
Comparison: pysvn vs. subprocess
| Feature | pysvn (Recommended) |
subprocess |
|---|---|---|
| Ease of Use | High. Native Python objects and methods. | Low. Requires parsing command-line strings and output. |
| Error Handling | Excellent. Raises specific pysvn.ClientError exceptions. |
Manual. Must check return codes and parse stderr. |
| Features | Comprehensive. Supports almost all SVN operations (status, blame, locks, etc.). | Limited. Only what the svn command-line tool can do. |
| Dependencies | Requires pysvn package and native svn client. |
Requires only native svn client. |
| Portability | Good, but requires a binary install for each platform. | Excellent, as long as svn is installed on the system. |
Conclusion
For any serious application or script that needs to interact with SVN, pysvn is the clear winner. It provides a robust, Pythonic, and feature-rich interface that is far easier to work with than manually parsing command-line output.
Use the subprocess method only for very simple, throwaway scripts where you don't want to add another dependency.
