Reloading and Caching
Flywheel SDK container objects are snapshots of server state at the time they were fetched. As your script runs — calling update(), uploading files, or waiting for gears to complete — the server state can diverge from what the local object reflects. This page covers two strategies for managing that gap: knowing when to call reload() to refresh a stale object, and caching container lookups so that the same data is not fetched more than once.
Reloading Strategies
When you call update() on a container, the local Python object is not automatically refreshed — it still reflects the state at the time it was first fetched. Similarly, containers returned by finders may not include all fields. Understanding when reload() is necessary — and when it is not — avoids both stale-data bugs and redundant requests.
When reload() is necessary
After calling update() — the SDK does not re-fetch the object after a write. Call reload() if you need the current server state immediately after updating.
session.update(label="ses-02")
session = session.reload() # reflects the new label
Before accessing .files or .analyses — containers returned by finders include summary fields but does not populate the full files and analyses lists by default (for response size optimization). Reload before using these lists if freshness matters.
acquisition = session.acquisitions.find_first("label=T1w")
acquisition = acquisition.reload()
for f in acquisition.files:
print(f.name, f.size)
Before reading info from a finder result — info may be absent or incomplete on objects returned from searches and finders. Reload to get the full payload.
session = project.sessions.find_first("label=baseline")
session = session.reload()
print(session.info)
Avoiding unnecessary reloads
A reload() call is a full API round trip. In a loop over hundreds of sessions, an unconditional reload() doubles the total request count.
| Situation | Action |
|---|---|
| Container was just fetched by ID | No reload needed — already fresh |
Need .files or .analyses | Reload before accessing |
Just called update() | Reload only if you need the updated fields |
Reading .info from a finder result | Reload before reading |
Only using .id, .label, or other top-level fields from the finder | No reload needed |
Selectively reloading only the containers that need updated data decreases the overall request count:
for session in project.sessions.iter():
if needs_file_list(session):
session = session.reload()
process_files(session.files)
Stale data detection
The SDK does not detect staleness automatically. There is no built-in version field or cache-validation header on container objects. You are responsible for tracking whether server state has changed since your last fetch.
Common signals that a container may be stale:
- A gear has run and may have added files or updated
info - Another process or user called
update()on the same container - You stored a reference to a container fetched earlier in a long-running script
In long-running scripts, call reload() or re-fetch containers by ID rather than reusing objects captured at the start:
for session_id in session_ids:
session = fw.get_session(session_id) # fresh on each iteration
process(session)
Caching Strategies
Every call to fw.lookup(), fw.get_project(), or any finder method is an HTTP request. In scripts that reference the same containers repeatedly, storing results locally eliminates redundant round trips.
Cache container lookups
Store containers in a dictionary keyed by ID or path when you expect to reference them more than once:
container_cache = {}
def get_container(container_id):
if container_id not in container_cache:
container_cache[container_id] = fw.get(container_id)
return container_cache[container_id]
For path-based lookups, use the path string as the cache key:
lookup_cache = {}
def cached_lookup(path):
if path not in lookup_cache:
lookup_cache[path] = fw.lookup(path)
return lookup_cache[path]
project = cached_lookup("my-group/my-project")
Local data structures
For multi-pass algorithms — where the same containers are looked up repeatedly — build an in-memory index from a single bulk query:
subjects_by_label = {s.label: s for s in project.subjects.iter()}
subject = subjects_by_label.get("SUB_01")
This pattern is especially useful in extract, transform, load (ETL) pipelines where you process subject or session records by label in a second pass over the data.
When to invalidate cache
A cached container object becomes stale when the server state has changed. Remove the entry from your cache — or mark it as dirty so it is re-fetched on next access — in these situations:
- You called
update()orupdate_info()on the container - You uploaded or deleted a file on the container
- A gear run completed and may have modified the container
session.update(label="ses-02")
session_cache.pop(session.id, None) # force re-fetch on next access
For long-running scripts, avoid persisting the cache across the entire run. Re-fetch containers at the start of each major work unit to ensure you are working with current data.
Related Topics
- Core Concepts: Containers —
reload(),update(), and CRUD operations