sftppath
pathlib for SFTP servers. SFTPPath("/srv/data/report.txt", host="files.example.org",
user="deploy") has the method names, signatures and exception types of
pathlib.Path, over paramiko or
asyncssh. It needs no URI and builds on
pathapi alone, which holds the
Path base class, glob, walk and PathSyncer. With
uripath installed the same package also
provides the sftp: scheme: URIPath("sftp://deploy@files.example.org/srv/data").
Deliberate behavioral differences from pathlib are listed, with their reasons,
in Divergences from pathlib.
Installation
pip install "sftppath[paramiko]" # or "sftppath[asyncssh]", or both
pip install "sftppath[uri]" # adds uripath and with it the sftp: scheme
Neither SSH library is required to import the package or to build, join and
compare paths; the first request of a path raises an ImportError that names
both extras when neither is installed. With both installed, asyncssh is used,
and it also runs recursive copy() and rm() as concurrent requests.
| Install | Adds |
|---|---|
pip install sftppath |
the path and the backends' contract (no SSH library) |
pip install "sftppath[paramiko]" |
the paramiko backend, SFTPBackend |
pip install "sftppath[asyncssh]" |
the asyncssh backend, AsyncSSHBackend |
pip install "sftppath[uri]" |
uripath and the sftp: scheme |
pip install "sftppath[all]" |
all three |
Tour
A path on a server: the host, port, user and password go in as keywords; a
path with no backend= builds its own and nothing connects until the first
request:
from sftppath import SFTPPath
report = SFTPPath("/srv/data/report.txt", host="files.example.org", user="deploy")
print(report.read_text())
for child in report.parent.iterdir():
print(child.name, child.stat().st_size)
One connection for many paths: a backend is the connections to one server and account; paths that share it share its connections:
from sftppath import SFTPBackend, SFTPPath
with SFTPBackend("files.example.org", user="deploy", timeout=10) as backend:
root = SFTPPath("/srv/data", backend=backend)
(root / "out").mkdir(exist_ok=True)
(root / "out" / "n.txt").write_text("1")
root.copy(SFTPPath("/srv/backup", backend=backend), recursive=True)
The scheme: with uripath installed, the URI of the server works too, and
the same classes do the work:
from uripath import URIPath
print(URIPath("sftp://deploy@files.example.org/srv/data/report.txt").read_text())
See SFTP paths and The sftp scheme.