data-management.md
265 lines · skills/latchbio-integration/references/data-management.md at 5f2bc03
Latch Data and Remote Paths
This reference distinguishes the two supported Python data models:
LPathis the modern,pathlib-like API for explicit remote operations.LatchFileandLatchDirare the established workflow parameter types for automatic task staging and output upload.
Do not assume methods from one model exist on the other. In particular, LatchDir.glob() is not a current SDK API.
Choosing an API
Use LPath when you need to:
- Inspect, upload, download, copy, list, or delete a remote path explicitly
- Work from scripts, Pods, Plots, or task code
- Avoid automatic transfer of an entire directory
- Store an
LPathvalue in Registry with SDK 2.67.22+
Use LatchFile or LatchDir when you need to:
- Expose a file or directory in a workflow form
- Automatically stage an input onto a task machine
- Automatically upload a returned task output
- Compose with older workflows or
latch.verifiedwrappers
It is normal to accept a LatchFile in a workflow and construct an LPath from its remote_path for a targeted remote operation.
Latch URLs
Common forms include:
latch:///path/in/current-workspace
latch://12345.account/path/in/workspace
latch://shared/path/to/shared-data
latch://67890.nodelatch:///...resolves relative to the active or execution workspace.- Account-qualified URLs avoid ambiguity across workspaces.
- Node URLs address a Latch Data object by immutable numeric ID.
- Shared URLs refer to data shared across accounts.
Do not concatenate URLs with filesystem utilities that discard the URL scheme. LPath supports / for child paths.
Metadata and listing
from latch.ldata.path import LPath
root = LPath("latch:///welcome")
if root.exists():
print(root.node_id())
print(root.name())
print(root.is_dir())
# size_recursive() can be slow for large directory trees.
for child in root.iterdir():
print(child.path, child.content_type(), child.size(), child.modify_time())iterdir() is shallow. It returns an iterator of child LPath objects and does not recursively traverse nested directories.
modify_time() (added in 2.76.9) returns a datetime or None; it is not a content checksum. size_recursive() can be expensive on large directories. Use ordinary file sizes unless recursive totals are needed.
Metadata is cached for the lifetime of the object after a lookup. Call fetch_metadata() after an external rename or modification when fresh values are required.
Download
Always provide an explicit destination for durable files:
from pathlib import Path
from latch.ldata.path import LPath
remote = LPath("latch:///inputs/design.csv")
local = remote.download(Path("work/design.csv"), cache=True)
print(local.read_text(encoding="utf-8"))Without a destination, the SDK downloads beneath ~/.latch/lpath/ and registers the temporary directory for cleanup when the process exits. Do not rely on that path after process termination.
With cache=True, the SDK uses the remote version identifier and local extended attributes where supported. Explicit paths plus caching are especially important in long-lived Pods and Plots. SDK 2.77.1 removed the pyxattr dependency: on macOS it invokes the system xattr command; on Linux it uses os.*xattr. Use a filesystem supporting extended attributes. Setting cache=False does not disable the post-download attribute write in this release, so it is not a workaround for an unsupported filesystem.
Upload
The destination's parent must exist:
from pathlib import Path
from latch.ldata.path import LPath
destination_dir = LPath("latch:///results/run-001")
destination_dir.mkdirp()
report = destination_dir / "report.txt"
report.upload_from(Path("report.txt"))upload_from accepts either a local file or directory. Avoid concurrent writes to the same destination.
Remote copy and delete
from latch.ldata.path import LPath
source = LPath("latch:///results/run-001/report.txt")
backup = LPath("latch:///archive/run-001/report.txt")
source.copy_to(backup)Deletion is recursive and destructive:
target = LPath("latch:///scratch/run-001")
target.rmr()Before rmr():
- Print or otherwise surface the exact resolved path.
- Confirm it is not a workspace root, shared production folder, or active workflow output.
- Obtain user confirmation unless deletion was already explicit.
LatchFile and LatchDir
These types carry both a local execution path and an optional remote path:
from pathlib import Path
from latch import small_task
from latch.types import LatchFile
@small_task
def summarize(input_file: LatchFile) -> LatchFile:
source = Path(input_file.local_path)
output = Path("/root/summary.txt")
output.write_text(
f"name={source.name}\nbytes={source.stat().st_size}\n",
encoding="utf-8",
)
return LatchFile(str(output), "latch:///results/summary.txt")For a passed input:
local_pathis the staged path on the task machine.remote_pathidentifies its source in Latch Data or S3.
For a returned value:
- The first constructor argument is the local file or directory.
- The second argument is the remote destination.
Use LatchOutputFile and LatchOutputDir in workflow signatures for destinations that may not exist yet:
from latch.types import LatchOutputDir, LatchOutputFileRaw lines 155 to 193Directory behavior
Returning a local LatchDir to an existing remote directory adds or updates the returned children. It does not imply deletion of unrelated remote files. Do not depend on this merge behavior as a synchronization or cleanup strategy.
LatchDir.iterdir() lists children of a remote directory. For globbing local task outputs into remote LatchFile values, use file_glob:
from latch import small_task
from latch.types import LatchFile, file_glob
@small_task
def collect_fastq_outputs() -> list[LatchFile]:
# Run the scientific tool here; it must create outputs/*.fastq.gz.
return file_glob("outputs/*.fastq.gz", "latch:///results/fastq/")Raw lines 194 to 213Data CLI
Inspect help for the installed version before scripting a command:
latch --version
latch cp --help
latch sync --helpCommon operations:
# List
latch ls latch:///inputs
# Upload or download
latch cp ./sample.fastq.gz latch:///inputs/sample.fastq.gz
latch cp latch:///results/report.html ./report.html
# Create parents
latch mkdirp latch:///results/run-001
# Synchronize a local tree to a remote directory
latch sync ./results latch:///results/run-001
# Recursive removal — confirm the target first
latch rmr latch:///scratch/run-001Prefer mkdirp and rmr; the older mkdir, rm, touch, and open commands were deprecated.
Reliability and Security
- Never print signed download URLs or authentication headers.
- Avoid loading a whole remote directory when only one file is needed.
- Use unique run destinations to prevent concurrent output collisions.
- Validate local checksums or scientific file integrity when correctness depends on complete transfer.
- Treat mounted cloud paths according to the source bucket's access policy.
- Keep workspace IDs explicit in automation that can access several workspaces.
- Do not call data mutations at module import time.
Official Sources
- Remote files (
LPath): https://wiki.latch.bio/workflows/sdk/api/working-with-files - Legacy file support: https://wiki.latch.bio/workflows/sdk/python/legacy-file-support
- Latch URLs: https://wiki.latch.bio/workflows/sdk/python/latch-urls
- Data CLI: https://wiki.latch.bio/data/data-command-line
- Data overview: https://wiki.latch.bio/data/overview
LPathsource in the 2.77.1 release commit: https://github.com/latchbio/latch/blob/b3768e65c6d496868f6e530f11977d857ad85dc7/src/latch/ldata/path.py