tboardfs
Mount and inspect TensorBoard event logs as ordinary files.
tboardfs has two access modes:
- Filesystem mode mounts a log directory with FUSE.
- Command mode inspects or copies the virtual content of one event file.
Both modes use the same virtual paths for TensorBoard tabs such as scalars, images, tensors, meshes,
pr_curves, hparams, and custom_scalars.
Filesystem Mode
Mount a TensorBoard log directory:
tboardfs SOURCE MOUNTPOINT
For non-developers, the simplest way to run it without cloning this repository or managing a local virtual environment is:
uvx tboardfs SOURCE MOUNTPOINT
Example:
tboardfs runs/experiment-1 mnt/tboardfs
ls mnt/tboardfs
cat mnt/tboardfs/train/scalars/loss.json
Mount mode is the primary workflow for browsing full log directories. It exposes run directories and supported sidecars such as projector/profile files.
A run directory inside another run is a directory beside the tabs of that run. When its name is also an entry of that
run, such as the run exp/scalars below the run exp, which has the tab scalars, it gets ~2 (then ~3, and so on)
and tboardfs logs a warning once. The run exp/scalars is then under /exp/scalars~2/, and /exp/scalars/ has only
the scalars of exp. The runs below a renamed directory follow it. A directory that has the name scalars~2 on disk
keeps that name; the renamed directory then gets ~3.
Symlinked directories in the source are followed, so a run kept elsewhere and linked into the log directory is a run under the link name. A directory that several links reach is shown once, under the first path in sorted order, and link loops end. Sidecar files of a linked run may resolve inside its real run directory; other links out of the source stay hidden. Do not link to the mountpoint from inside the source: reading the link would call back into the mount and stop it.
Each open file keeps the version it had when it was opened, so reads stay whole while a training run writes new events.
A new open shows the new data. Mounted files use direct I/O: shared memory maps (mmap with MAP_SHARED,
np.load(..., mmap_mode="r")) fail with ENODEV; private maps (mmap_mode="c") and plain reads work.
--refresh-age-seconds (default 60) sets how old the data can get before the next file operation checks the source
again. A check lists each directory once and opens only the event files whose device, inode, size, mtime or ctime
changed. Every write changes the ctime, so a rewritten file is read again even when its mtime is set back. Only a
rewrite to the same size within one timestamp tick of a filesystem with coarse timestamps is not seen until the next
change. On a network filesystem, a larger value makes fewer round trips.
Rendered files are kept in memory, so ls -l followed by cat renders a file once. --cache-size-mb sets the memory
for this cache (default 1024; 0 turns it off). When the cache goes over the limit, the least recently used files are
dropped until half the limit is left. New events in a run make only the files of that run render again.
Files and directories belong to root (uid and gid 0) by default. --user-owner gives them to the user and group that
mount the filesystem; --root-owner is the default. The permissions stay read-only for everyone (0444 files, 0555
directories).
--scalar-format selects the scalar and histogram table formats, as a comma-separated list of json, tsv, csv, and
npz (default json,tsv,npz). --step-digits sets the zero-padding width of step file names, from 1 to 20 (default
6). --loglevel takes a loguru level name in any case. Both commands refuse other values with a usage error.
A resumed run hides the rows it replaces, as TensorBoard does. When a writer marks a restart at step S (a
SessionLog.START event, for example from PyTorch SummaryWriter(purge_step=S)), rows written before it with step S or
higher are not shown. Graphs stay. This applies to event files with file version 2 or later, which all current writers
produce.
Command Mode
Use tboardfs-file when mounting is unavailable or when you need scripted access to TensorBoard event files.
List every virtual file:
tboardfs-file list events.out.tfevents.123
List files below a virtual path:
tboardfs-file list events.out.tfevents.123 /meshes
Extract one virtual file to stdout:
tboardfs-file get events.out.tfevents.123 /scalars/loss.json -o -
Extract one virtual file to disk:
tboardfs-file get events.out.tfevents.123 /images/sample/000001.png -o sample.png
The virtual path may be written with or without the leading /. If -o points to an existing directory, or to a
missing path ending in /, get writes the virtual file basename inside that directory.
tboardfs-file get events.out.tfevents.123 scalars/loss.json -o exported/
Copy the full virtual tree:
tboardfs-file copy-all events.out.tfevents.123 exported-event
For one event file, command mode exposes tab directories directly at the root, for example /scalars, /images, and
/meshes, without sibling sidecars. SOURCE can also be a run directory or a log directory. Then the commands show the
same tree as a mount of that directory: a run directory has its tabs at the root, a log directory has one directory per
run, and both include sidecars.
get refuses to overwrite existing files unless --force is provided. copy-all copies files in deterministic
virtual-path order. If it reaches an existing target without --force, it stops, reports how many files were already
copied, lists those virtual paths, prints the conflicting output path, and suggests --force. After a successful copy,
copy-all reports the number of copied files.
Use --skip-existing to leave existing output files untouched and continue copying the rest of the tree:
tboardfs-file copy-all events.out.tfevents.123 exported-event --skip-existing
Each skipped virtual path is reported as a warning on stderr. --force and --skip-existing are mutually exclusive.
Supported Objects
A tag is a path below its tab, so train/loss is /scalars/train/loss.json. Empty parts of a tag are left out, and a
tag without a name is untagged. When two tags of a run get the same path, such as a/b and a//b, the tag that the
path spells keeps it. The other tag gets ~2 (then ~3, and so on) on its last part in every tab, and tboardfs logs a
warning once. A tag directory can also have the name of a file, such as the tag a/000001.npy beside the step file
000001.npy of the tag a, or the tag loss.json/x beside /scalars/loss.json. Then the directory gets ~2 in every
tab, such as /tensors/a/000001.npy~2/, and the file keeps its name. When two files without a tag meet at one path,
such as two profile sidecars a and a/c, the first file stays, and tboardfs logs a warning.
The virtual tree covers these TensorBoard objects:
- Scalars: full-series
json,tsv, andnpzexports under/scalars. Theepochcolumn of scalar and histogram tables is theepochscalar written at the same step, as PyTorch Lightning writes it. A step without anepochscalar has the last epoch written before it. - Custom scalars: layout JSON under
/custom_scalars. - Images: encoded image files under
/images. A TensorFlow 2 image summary with more than one image gives one file per image,<step>_<i>, such as000001_0.png. - Audio: encoded audio files under
/audio, with the same<step>_<i>names for more than one clip. - Videos: encoded video/GIF outputs under
/videos, including raw subpaths when present. - Histograms: per-step
json,tsv, andnpzexports under/histograms. TensorFlow 1 and TensorFlow 2 histogram summaries give the same tables. As in TensorBoard, a TensorFlow 1 histogram runs from its minimum to its maximum, without the empty buckets at its two ends, and a histogram of no values has no step file. - Distributions: per-step distribution tables under
/distributions, with the values that the TensorBoard Distributions tab shows. Thepercentilecolumn has 9 values: 0, 6.68, 15.87, 30.85, 50, 69.15, 84.13, 93.32 and 100, which are the mean and ±1, 2 and 3 standard deviations of a normal distribution. Each value interpolates linearly inside its histogram bucket. - Text summaries: UTF-8 text files under
/text. A summary with one string is that text. A summary with many strings is a Markdown table, as TensorBoard shows it: a vector is one column, and a tensor with more than 2 dimensions shows its first 2-D slice after a warning. A.jsonfile next to the table keeps the shape and the exact strings. - Meshes: per-step
json,npz, and Wavefrontobjexports under/meshes. The OBJ file has one object (o mesh_<i>) per batch element when the batch has more than one mesh. Vertex colors follow the coordinates asr g bvalues in [0, 1], which MeshLab and Blender read. A mesh without faces is an OBJ point cloud. Theplyfile is a binary PLY mesh, which keeps the coordinates exactly: float32 coordinates asfloat, other numbers asdouble, and colors asucharred green blue. A point cloud has nofaceelement. A batch is one PLY mesh, with the faces of a later element offset by the vertices before it, and acomment mesh_<i> vertices <start> <count>line per element. Faces that are not vertex indices, and colors that are not whole numbers from 0 to 255, are not in the PLY file; thenpzfile keeps them. The path of a mesh is its tag without the_VERTEX,_FACEor_COLORsuffix, sotrain/cloud_VERTEXis under/meshes/train/cloud. A tag without that suffix uses the mesh name, which thejsonfile keeps. This is different from TensorBoard, which groups meshes by the mesh name only and thus mixestrain/cloudandval/cloud. - PR curves: per-step
json,tsv, andnpyexports under/pr_curves. The tables have one row per threshold, with the columnsthreshold,true_positives,false_positives,true_negatives,false_negatives,precision, andrecall. The thresholds are evenly spaced in [0, 1], as in TensorBoard. The.npyfile keeps the raw[6, N]tensor. A tensor of another shape keeps genericvalue_<i>columns. - HParams: merged experiment/session/metric JSON under
/hparams. The metrics are the declared metric tags, or all scalar tags when the run declares no experiment, as in TensorBoard. Each metric has its last value, ornullwithout data. Metrics in a sub-run group (for example Kerasvalidation) have no value here; read them from the scalars of that run.sessionslists every session of the run;session_startandsession_endare the first ones, as in TensorBoard. Thehparams.yamlfile that PyTorch Lightning writes in the run directory is also in/hparams. - Tensors: tensor arrays as
npyplus compact JSON or native blob files under/tensors. Every numeric TensorFlow dtype that NumPy has keeps its dtype, including float16, int8, int16, uint16 and complex. NumPy has no bfloat16, so bfloat16 tensors are widened to float32; this is exact. Float8 and 4-bit tensors are not decoded. String tensors are NumPy text arrays (dtypeU), sonp.loadreads them withoutallow_pickle. A numeric tensor written without a plugin name is also a tensor here. A tensor with one value is a scalar instead. A tensor of 1 KiB or more also has its raw bytes as a native blob file, unless its plugin has its own tab: a large histogram, PR curve, mesh or text summary is only in that tab. - Graphs: graph protobuf files under
/graphs.graph.pbis the graph that TensorBoard shows: the newest graph that the event files hold as agraph_def, which TensorFlow 1 and PyTorchadd_graphwrite, or without one, the graph of the newest TensorFlow 1 meta graph. A run with severalgraph_defgraphs also hasgraph_<i>.pbfor each one, in write order.meta_graph.pbis the newest TensorFlow 1MetaGraphDef, withmeta_graph_<i>.pbin the same way. A TensorFlow 2 graph summary is in/graphs/<tag>. The Keras model config that the Keras TensorBoard callback writes is<step>.json, and the RunMetadata oftf.summary.trace_exportis<step>.run_metadata.pb. Next to each one,<step>.conceptual.pbor<step>.pbis the GraphDef that the TensorBoard Graphs tab shows for it. A TensorFlow 1 tagged RunMetadata, whichFileWriter.add_run_metadataand PyTorchadd_graphwrite, is also/graphs/<tag>/<step>.run_metadata.pb. Next to each RunMetadata,<step>.run_metadata.pbtxtis the profile text that the Graphs tab shows for it. TensorBoard 2.21 cannot draw a functional model inside a Sequential model from a Keras 3 config, because it reads the one input of the nested model as three inputs; tboardfs draws it with that one input. A malformed summary, RunMetadata or meta graph has no converted file (GraphDef, profile text orgraph.pb); tboardfs logs a warning for it once, when it reads the event. Its native file stays. - Projector and profile sidecars: available in filesystem mode, and in command mode for a directory, under
/projectorand/profile; command mode for one event file omits sibling sidecar files. The embedding files thatprojector_config.pbtxtnames (tensor_path,metadata_path, spriteimage_path,bookmarks_path), such as the<step>/<tag>/tensors.tsvfiles of PyTorch and tensorboardXadd_embedding, are under/projectorat the same relative paths. Only relative paths to files of the run are followed, and only the first MiB of the config is read. - Other plugin JSON payloads: exposed under
/pluginswhen no typed tab handles them.
A record that tboardfs cannot convert has no file. Such records are an hparams or mesh record whose plugin content does not decode, a custom scalar summary whose tensor has no layout that decodes, and the malformed graph data above. tboardfs logs one warning for each, when it reads the event. The other values of the same event stay. A native file, which holds the stored bytes, always stays.
Output Rules
All .json files are strict JSON (RFC 8259). Infinities are written as the strings "Infinity" and "-Infinity". In
scalar, histogram and other table files, NaN is a missing value and is written as null. In other JSON files, NaN is
written as the string "NaN", as in protobuf JSON. A complex number is written as its [real, imag] pair. Bytes that
are valid UTF-8 are written as text. Other bytes are written as {"base64": "..."}.
An event without a step field is at step 0, as in TensorBoard: writers leave out step 0.
tboardfs-file list prints virtual file paths to stdout, one per line. tboardfs-file get -o - writes raw bytes to
stdout. Extraction status, warnings, errors, copied-file counts, skipped-path warnings, copied-path conflict reports,
and overwrite hints are written to stderr through Loguru/Click so stdout remains safe for pipelines.
License
MIT
Star History
Metadata
Release files for tboardfs 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tboardfs-0.3.0.tar.gz | 84.9 kB | Without provenance | Details for tboardfs-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tboardfs-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for tboardfs-0.3.0-py3-none-any.whl |
Total release size: 190.8 kB
Release files / tboardfs-0.3.0.tar.gz
| Download URL | tboardfs-0.3.0.tar.gz |
|---|---|
| Size | 84.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
35fb18bd95ac65adba76cabc3b8ca27865008111ca59c628f6b80e209e5539b1
|
|
BLAKE2b-256 checksum How to use checksums |
5ac7da773500a9991b26e31fd4e9e183b47de816cb085b37bad1b532b6d42e7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.10
|
Release files / tboardfs-0.3.0-py3-none-any.whl
| Download URL | tboardfs-0.3.0-py3-none-any.whl |
|---|---|
| Size | 105.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6178e013dd615c7c77780bde35a9faea2c5b42606868a4fa8da07ad8510fb0f2
|
|
BLAKE2b-256 checksum How to use checksums |
0f6790c8c7773b26e0609fae83701bbb6879eb1b5ba200feaf4fe5be71c99565
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.10
|
Security for tboardfs 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.