videoflow.utils package
Submodules
videoflow.utils.downloader module
- videoflow.utils.downloader.get_file(fname: str, origin: str | list, untar: bool = False, md5_hash: str | None = None, file_hash: str | None = None, cache_subdir: str = 'models', hash_algorithm: str = 'auto', extract: bool = False, archive_format: str | list | None = 'auto', cache_dir: str | None = None) str[source]
Copied from Keras repository.
Downloads a file from a URL if it not already in the cache. By default the file at the url origin is downloaded to the cache_dir ~/.videoflow, placed in the cache_subdir models, and given the filename fname. The final location of a file example.txt would therefore be ~/.videoflow/models/example.txt. Files in tar, tar.gz, tar.bz, and zip formats can also be extracted. Passing a hash will verify the file after download. The command line programs shasum and sha256sum can compute the hash.
- Arguments:
- fname: Name of the file. If an absolute path /path/to/file.txt is
specified the file will be saved at that location.
origin: Original URL of the file.
- untar: Deprecated in favor of ‘extract’.
boolean, whether the file should be decompressed
- md5_hash: Deprecated in favor of ‘file_hash’.
md5 hash of the file for verification
- file_hash: The expected hash string of the file after download.
The sha256 and md5 hash algorithms are both supported.
- cache_subdir: Subdirectory under the Keras cache dir where the file is
saved. If an absolute path /path/to/folder is specified the file will be saved at that location.
- hash_algorithm: Select the hash algorithm to verify the file.
options are ‘md5’, ‘sha256’, and ‘auto’. The default ‘auto’ detects the hash algorithm in use.
extract: True tries extracting the file as an Archive, like tar or zip.
- archive_format: Archive format to try for extracting the file.
Options are ‘auto’, ‘tar’, ‘zip’, and None. ‘tar’ includes tar, tar.gz, and tar.bz files. The default ‘auto’ is [‘tar’, ‘zip’]. None or an empty list will return no matches found.
- cache_dir: Location to store cached files, when None it
defaults to the [Keras Directory](/faq/#where-is-the-keras-configuration-filed-stored).
- Returns
Path to the downloaded file
- videoflow.utils.downloader.validate_file(fpath: str, file_hash: str, algorithm: str = 'auto', chunk_size: int = 65535) bool[source]
Validates a file against a sha256 or md5 hash.
- Arguments:
fpath: path to the file being validated
file_hash: The expected hash string of the file. The sha256 and md5 hash algorithms are both supported.
algorithm: Hash algorithm, one of ‘auto’, ‘sha256’, or ‘md5’. The default ‘auto’ detects the hash algorithm in use.
chunk_size: Bytes to read at a time, important for large files.
- Returns:
Whether the file is valid
videoflow.utils.generic_utils module
- class videoflow.utils.generic_utils.DelayedInterrupt(signals: int | list[int] | tuple[int, ...])[source]
Bases:
objectclass based on: http://stackoverflow.com/a/21919644/487556
It delays interrupts until the code exits the entered block
- class videoflow.utils.generic_utils.DelayedKeyboardInterrupt[source]
Bases:
DelayedInterrupt
- class videoflow.utils.generic_utils.Progbar(target: int | None, width: int = 30, verbose: int = 1, interval: float = 0.05, stateful_metrics: Iterable[str] | None = None)[source]
Bases:
objectDisplays a progress bar.
- Arguments
target: Total number of steps expected, None if unknown.
width: Progress bar width on screen.
verbose: Verbosity mode, 0 (silent), 1 (verbose), 2 (semi-verbose)
stateful_metrics: Iterable of string names of metrics that should not be averaged over time. Metrics in this list will be displayed as-is. All others will be averaged by the progbar before display.
interval: Minimum visual progress update interval (in seconds).
- update(current: int, values: list | None = None) None[source]
Updates the progress bar.
- Arguments
current: Index of current step.
values: List of tuples: (name, value_for_last_step). If name is in stateful_metrics, value_for_last_step will be displayed as-is. Else, an average of the metric over time will be displayed.
videoflow.utils.graph module
- videoflow.utils.graph.flatten(items: Iterable) list[source]
Returns flattened iterable from any nested iterable
- videoflow.utils.graph.has_cycle(producers: Sequence[Node]) bool[source]
Used to detect if the graph is not acyclical. Returns true if it finds a cycle in the graph. It begins exploring the graph from producers down all the way to consumers.
- videoflow.utils.graph.topological_sort(producers: Sequence[Node]) list[Node][source]
Creates a topological sort of the computation graph.
- Arguments:
producers: a list of producer nodes, that is, nodes with no parents.
- Returns:
stack: a list of nodes in topological order. If a node A appears before a node B on the list, it means that node A does not depend on node B output
videoflow.utils.parsers module
videoflow.utils.plugins module
Third-party registration via importlib.metadata entry points.
Videoflow’s extension points are plain dict/list registries with an explicit
register_*() function, pre-seeded with the built-ins. That covers the common
case, where the code doing the registering is imported anyway (a component
module the worker loads via VF_NODE_CLASS registers its own payload codecs
on import).
It does not cover the case where nothing imports the extension first — a blob
store selected by URL scheme in a config file, say, or a host-side
videoflow debug decode that must understand a vendor payload type without
knowing which package defines it. For those, a package declares an entry point
and videoflow imports it on demand.
Stdlib only, by design: an extension mechanism that needs its own dependency is
a worse trade than the if/elif it replaces.
- videoflow.utils.plugins.load_plugin_group(group: str) None[source]
Imports every extension registered in the
importlib.metadataentry-point groupgroup, so itsregister_*()side effects take hold. Idempotent: a group is scanned at most once per process.Each entry point may resolve to either a module (imported for its top-level
register_*()calls) or a callable (imported and then called). A plugin that raises is logged and skipped rather than propagated — one broken third-party package must not stop a worker from starting, since the registration it was providing may not even be needed by this flow.- Arguments:
group: entry-point group name, e.g.
'videoflow.blob_stores'.
videoflow.utils.system module
Host GPU inspection.
The one place videoflow enumerates physical GPU ordinals. Two faces of the
multi-GPU visibility contract (RFC 0003) live here: granted_gpus() is the
component-facing side — inside a worker, the visible devices are exactly the
granted devices, numbered 0..n-1 — and visible_physical_gpus() is the
engine-facing side, the pool of physical ordinals the local engine partitions
across workers (engines/local.py). Kubernetes workers normally don’t need
either (the device plugin already masks the container to its grant), but
non-CUDA runtimes and native wrappers can call granted_gpus() instead of
parsing CUDA_VISIBLE_DEVICES themselves.
- videoflow.utils.system.NVIDIA_SMI_QUERY = ('--query-gpu=index,uuid,name,memory.total,memory.used', '--format=csv,noheader,nounits')
one CSV row per physical GPU, memory in MiB (
nounits).-Ladds the MIG UUIDs.- Type:
The
nvidia-smiquery the local allocation backend inventories from
- videoflow.utils.system.NVIDIA_SMI_TIMEOUT_SECONDS = 5
Bound on the
nvidia-smiprobe — a wedged driver otherwise hangs the local engine’s launch path indefinitely. Normal responses take well under 1s.
- videoflow.utils.system.apply_mask(devices: Sequence[DeviceIdentity], mask: Sequence[str] | None) list[DeviceIdentity][source]
The devices a
CUDA_VISIBLE_DEVICESmask exposes, in mask order, as the CUDA runtime resolves it: an integer entry is a physical ordinal, aGPU-…entry a card UUID (a unique prefix suffices), aMIG-…entry a MIG instance UUID. The runtime’s rules, as observed on driver R595 (plan Phase 4, ALLOC-015): enumeration stops at the first entry that names no device — an unknown UUID, an out-of-range ordinal, or an entry of the other form in a mixed list — and a mask naming one device twice is invalid as a whole (cudaErrorInvalidDevice: nothing is exposed).None(unset) exposes every physical card; MIG instances are never exposed implicitly.
- videoflow.utils.system.get_gpus_available_to_process() list[int]
Deprecated pre-RFC-0003 name for
granted_gpus().
- videoflow.utils.system.get_number_of_gpus() int[source]
The number of physical GPUs in the system, 0 when
nvidia-smiis missing, failing or hung. Counts theGPU <n>:lines ofnvidia-smi -L, so MIG instances are not enumerated: a MIG-enabled card counts once, even though its compute is only reachable through its MIG devices, which videoflow does not address locally (seevisible_physical_gpus()).
- videoflow.utils.system.get_system_gpus() set[int][source]
Returns the ids of gpus in the machine as a set of integers
- videoflow.utils.system.granted_gpus() list[int][source]
The calling process’s granted devices as valid CUDA indices
[0..n-1](RFC 0003). Correct in a pod (the device plugin renumbers the grant) and locally (CUDA renumbers theCUDA_VISIBLE_DEVICESmask), so a component can both checklen(granted_gpus())against a hard device minimum inopen()and place work with.to(f'cuda:{i}')for each entryi.Under an integer mask (or none) this counts whole physical cards. Under a UUID mask it counts the mask’s resolved entries — one per
GPU-…card and one perMIG-…instance, in mask order, which is what CUDA enumerates (whether a driver exposes more than one MIG instance to a process is the driver’s call; the count reports what the mask names, andruntime.gpucheckreports what was delivered).
- videoflow.utils.system.host_devices_observed() Known[list[DeviceIdentity]] | Unknown[source]
Every physical GPU (and MIG instance) of this host, with UUIDs and memory — or
Unknownwhennvidia-smiis absent, failing or hung. Never “no GPUs” for a failed read: the local allocation backend refuses to grant on an unobserved host rather than under-deliver silently (ALLOC-014).
- videoflow.utils.system.mask_entries(value: str | None) list[str] | None[source]
The entries of a
CUDA_VISIBLE_DEVICESvalue (None when unset;[]for the hide-all idiom'').
- videoflow.utils.system.parse_smi_list(text: str) list[DeviceIdentity][source]
nvidia-smi -Las identities: one per physical GPU, and one per MIG instance (mig_uuidset,mig_profileits1g.24gb-style name,uuidits parent card’s). A MIG-enabled card’s compute is reachable only through its instances, which is why they are enumerated here and not byget_number_of_gpus.
- videoflow.utils.system.parse_smi_query(csv_text: str) list[DeviceIdentity][source]
nvidia-smi --query-gpu=index,uuid,name,memory.total,memory.usedrows as identities (memory in bytes).
- videoflow.utils.system.parse_smi_used(csv_text: str) dict[str, int][source]
uuid -> memory.usedin bytes from the same query, for peak-memory admission.
- videoflow.utils.system.visible_devices() list[DeviceIdentity][source]
The devices the calling process can address, honouring an inherited
CUDA_VISIBLE_DEVICESby ordinal, card UUID or MIG UUID (RFC 0006 plan Phase 4; the identity-carrying counterpart ofvisible_physical_gpus). Empty when the host cannot be observed: callers that must tell “no GPUs” from “no answer” usehost_devices_observed.
- videoflow.utils.system.visible_physical_gpus() list[int][source]
The physical device ordinals visible to the calling process, sorted: the system’s GPUs intersected with
CUDA_VISIBLE_DEVICES(unset ⇒ all of them). A mask withGPU-…/MIG-…entries is resolved the way the CUDA runtime resolves it (apply_mask: identities vianvidia-smi -L, and nothing past the first entry that names no device), with a warning naming the entries the runtime would not expose. Engine-facing: this is the pool the local engine partitions into per-workerCUDA_VISIBLE_DEVICESmasks (engines/local.py). These are not validcuda:iindices under aCUDA_VISIBLE_DEVICESmask — CUDA renumbers the masked devices to0..n-1; components should usegranted_gpus()instead.MIG caveat: a MIG-enabled card contributes a single ordinal — its instances are not enumerated, and an integer
CUDA_VISIBLE_DEVICESentry cannot address a MIG slice (slices are pinned byMIG-<uuid>or granted by the Kubernetes device plugin), so the local engine never partitions below a whole card.