WebDAV4 Client Library
webdav4 is a modern Python library for interacting with WebDAV servers, providing both a low-level client (`WebdavClient`) and an `fsspec`-compatible filesystem (`WebdavFS`). It is currently at version 0.11.0 and is actively maintained, with regular releases addressing features and bug fixes. It aims to offer a robust and user-friendly way to manage files on WebDAV resources.
Common errors
-
ModuleNotFoundError: No module named 'webdav'
cause Attempting to import the old package name, `webdav`, which was renamed to `webdav4` in version 0.10.0.fixRun `pip install webdav4` and change all `import webdav` statements to `import webdav4` (or specific submodules like `from webdav4.client import WebdavClient`). -
webdav4.exceptions.WebdavError: 401 Unauthorized
cause Incorrect or missing authentication credentials (username/password), or the WebDAV server requires a different authentication method not correctly provided.fixDouble-check the `username` and `password` values passed to `WebdavFS` or `WebdavClient`. Ensure the URL is correct and includes the proper path to the WebDAV resource. Some complex setups might require specific `auth` parameters for `WebdavClient`. -
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate
cause The WebDAV server is using an SSL certificate that cannot be verified by your system's trusted CAs, typically a self-signed certificate.fixIf connecting to a server with a self-signed or untrusted certificate for development/testing, add `verify=False` to the `WebdavClient` or `WebdavFS` constructor, e.g., `WebdavFS(url=..., username=..., password=..., verify=False)`. -
FileNotFoundError: /path/to/nonexistent/file (or directory)
cause The specified file or directory path does not exist on the WebDAV server, or there's a case-sensitivity mismatch.fixVerify the exact path and case sensitivity of the file/directory on the WebDAV server. Use methods like `fs.ls('/')` to inspect available paths and ensure the target exists before attempting operations like `open`, `cat`, or `rm`.
Warnings
- breaking The package name was changed from `webdav` to `webdav4` starting with version 0.10.0. Projects using `import webdav` will fail with a `ModuleNotFoundError`.
- breaking The constructor signatures for `WebdavClient` and `WebdavFS` underwent significant changes in version 0.10.0. Specifically, `WebdavClient` now uses `base_url` instead of `url`, and the handling of authentication arguments has been refactored.
- gotcha Connecting to WebDAV servers with self-signed SSL certificates or untrusted Certificate Authorities (CAs) will cause `ssl.SSLCertVerificationError` by default due to strict certificate validation.
- gotcha When using `fsspec` directly to create a filesystem, ensure you use the `webdav` or `webdavs` protocol handler. The `url` parameter for direct `WebdavFS` instantiation expects `http://` or `https://` URLs, but `fsspec.open` expects `webdav://` or `webdavs://`.
Install
-
pip install webdav4
Imports
- WebdavClient
from webdav.client import WebdavClient
from webdav4.client import WebdavClient
- WebdavFS
from webdav.fs import WebdavFS
from webdav4.fs import WebdavFS
Quickstart
import os
from webdav4.fs import WebdavFS
# Replace with your WebDAV server details or set as environment variables
WEBDAV_URL = os.environ.get('WEBDAV_URL', 'http://localhost:8000/webdav/')
WEBDAV_USER = os.environ.get('WEBDAV_USER', 'user')
WEBDAV_PASS = os.environ.get('WEBDAV_PASS', 'password')
if not all([WEBDAV_URL, WEBDAV_USER, WEBDAV_PASS]):
print("Please set WEBDAV_URL, WEBDAV_USER, WEBDAV_PASS environment variables or update the script.")
exit(1)
try:
# Initialize WebdavFS
# For self-signed certificates or HTTP, you might need to add verify=False
fs = WebdavFS(
url=WEBDAV_URL,
username=WEBDAV_USER,
password=WEBDAV_PASS,
# verify=False # Uncomment if you have SSL certificate issues
)
print(f"Connecting to WebDAV server: {WEBDAV_URL}")
# List contents of the root directory
print(f"Listing contents of '/':")
for item in fs.ls('/', detail=True):
print(f" - {item['name']} (Type: {item['type']}, Size: {item.get('size', 'N/A')})")
# Example: Create a directory
test_dir_name = 'my_test_dir_webdav4'
if not fs.exists(test_dir_name):
fs.mkdir(test_dir_name)
print(f"Successfully created directory: {test_dir_name}")
else:
print(f"Directory '{test_dir_name}' already exists.")
# Example: Write and read a file
test_file_path = f'{test_dir_name}/hello.txt'
file_content = 'Hello, WebDAV4!'
with fs.open(test_file_path, 'wb') as f:
f.write(file_content.encode('utf-8'))
print(f"Wrote content to {test_file_path}")
with fs.open(test_file_path, 'rb') as f:
read_content = f.read().decode('utf-8')
print(f"Read content from {test_file_path}: '{read_content}'")
# Clean up (optional)
# fs.rm(test_file_path)
# print(f"Removed file: {test_file_path}")
# fs.rmdir(test_dir_name)
# print(f"Removed directory: {test_dir_name}")
except Exception as e:
print(f"\nAn error occurred: {e}")
print("Please ensure the WebDAV server is running and accessible, ")
print("and that WEBDAV_URL, WEBDAV_USER, WEBDAV_PASS environment variables are set correctly.")
print("If you are facing SSL issues, try adding `verify=False` to the WebdavFS constructor.")