File access

Modal Volumes or CloudBucketMounts can be attached to sandboxes. If you want to give the caller access to files written by the sandbox, you could create an ephemeral Volume that will be garbage collected when the app finishes:

with modal.Volume.ephemeral() as vol:
    sb = modal.Sandbox.create(
        volumes={"/cache": vol},
        app=my_app,
    )
    p = sb.exec("bash", "-c", "echo foo > /cache/a.txt")
    p.wait()
    sb.terminate()
    for data in vol.read_file("a.txt"):
        print(data)

Alternatively, if you want to persist files between Sandbox invocations (useful if you’re building a stateful code interpreter, for example), you can use create a persisted Volume with a dynamically assigned label:

session_id = "example-session-id-123abc"
vol = modal.Volume.from_name(f"vol-{session_id}", create_if_missing=True)
sb = modal.Sandbox.create(
    volumes={"/cache": vol},
    app=my_app,
)
p = sb.exec("bash", "-c", "echo foo > /cache/a.txt")
p.wait()
sb.terminate()
for data in vol.read_file("a.txt"):
    print(data)

If you want to pass data in and out of the Sandbox during execution, you can use a NetworkFileSystem mount. Avoid using NetworkFileSystems for most use cases, as they are slower than Volumes. Only use them if you need put data into the Sandbox or get data out during execution rather than before or after execution.

We are in the process of deprecating NetworkFileSystems in favor of Sandbox-specific filesystem APIs. If this sounds like it might be useful for your use case, please reach out and let us know!

with modal.NetworkFileSystem.ephemeral() as nfs:
    sb = modal.Sandbox.create(
        network_file_systems={"/mnt/nfs": nfs},
        app=my_app,
    )
    p = sb.exec("bash", "-c", "echo foo > /mnt/nfs/a.txt")
    p.wait()
    print(nfs.read_file("a.txt"))
    sb.terminate()