Launch dcmview from Python
Launch the same v0.4.1 Rust viewer after Python code has selected the files or cases to inspect.
Install the wrapper
Section titled “Install the wrapper”python -m pip install --user dcmview-py==0.4.1Supported wheels bundle the dcmview binary. The wrapper requires Python 3.9 or later.
Wait for the viewer to exit
Section titled “Wait for the viewer to exit”The default call blocks until the viewer stops and returns None after a successful exit:
from dcmview_py import view
view("./scan.dcm")Use a list to inspect multiple files or directories, and disable the automatic browser when working in a terminal or notebook:
from dcmview_py import view
view( ["./study", "./derived/segmentation.dcm"], browser=False, timeout=300, filters=["Modality=CT"],)timeout is an idle timeout that starts when the scan finishes; API or browser requests reset it. Filter fields accept snake_case names such as patient_id or DICOM keywords such as PatientID.
Interrupting a blocking call, for example with a notebook’s interrupt button, stops the viewer before the interrupt is raised.
Control a non-blocking session
Section titled “Control a non-blocking session”Set block=False to receive a handle:
from dcmview_py import view
handle = view("./study", browser=False, block=False)if handle is None: raise RuntimeError("expected a non-blocking handle")
print(handle.url)return_code = handle.stop()handle.url is the launch URL and ends in #token=…, the session’s access token. Open the complete link; the address without the fragment shows a page that asks for the access link. Printing it shows a credential, so keep it out of output you share.
A non-blocking call waits for the viewer’s URL, then up to five more seconds for its scan to finish. If the scan finds no DICOM files, the call raises subprocess.CalledProcessError instead of returning a handle. If no URL arrives within 30 seconds, the call warns and handle.url stays None until the server reports it.
Non-blocking viewers are stopped when the Python interpreter exits, so a finished script or a restarted notebook kernel does not leave a server running. Use a blocking call or the dcmview command when the viewer should outlive the script.
For deterministic cleanup, use the handle as a context manager:
from dcmview_py import view
with view("./study", browser=False, block=False) as handle: print(handle.url)The context manager calls stop() on exit. Local handles request graceful shutdown, then terminate and finally kill the subprocess only if it does not stop within the timeout.
Call the API with the access token
Section titled “Call the API with the access token”Every request to the viewer’s HTTP routes needs Authorization: Bearer <token>. A non-blocking handle for a local viewer exposes the two values a script needs: handle.base_url, the origin without the fragment, and handle.token.
import jsonfrom urllib.request import Request, urlopen
from dcmview_py import view
with view("./study", browser=False, block=False, vscode_bridge=False) as handle: request = Request( handle.base_url + "/api/files", headers={"Authorization": f"Bearer {handle.token}"}, ) with urlopen(request) as response: catalog = json.load(response)Both properties are None with a binary older than v0.4.0 and for a viewer routed into VS Code, which is why the example passes vscode_bridge=False. To choose the token yourself, set DCMVIEW_TOKEN in the environment before calling view(); the binary inherits it. The routes are an unsupported internal protocol and can change with any release.
Load annotations
Section titled “Load annotations”from dcmview_py import view
view( "./study", annotations="./embed_annotations.csv", browser=False,)See the annotation guide for CSV shape and in-memory editing behavior.
Mask identifiers for a shared screen
Section titled “Mask identifiers for a shared screen”Pass mask=True to start a masked session, the same as dcmview --mask:
from dcmview_py import view
view("./study", mask=True)The viewer replaces patient identifiers in everything it displays. This is a display aid, not de-identification: files are not modified, and burned-in pixel text, free text, and folder and file names are not masked. See Share your screen before you rely on it.
Control VS Code routing
Section titled “Control VS Code routing”With the dcmview VS Code extension active, view() opens the viewer in a VS Code webview when Python runs in a VS Code integrated terminal, or when its working directory is inside an open workspace folder. The second case covers notebooks started from the workspace. Anywhere else, the local viewer starts. The returned non-blocking handle is a ShutdownHandle in both cases and controls a VS Code-managed viewer through the same .url and .stop() interface. For a VS Code-managed viewer, handle.token and handle.base_url are None, and a DCMVIEW_TOKEN set only in the launching terminal or notebook is not forwarded: the viewer inherits the extension host’s environment and otherwise generates its own token.
Force a local subprocess when a browser window is preferable:
from dcmview_py import view
view("./study", vscode_bridge=False)You can also set DCMVIEW_VSCODE_BYPASS=1 for the process environment.
Run the module command
Section titled “Run the module command”The package also provides a module command. It and the dcmview and dcmview-py console scripts pass their arguments unchanged to the binary, so options, --help, and --version are the Rust CLI’s own:
python -m dcmview_py --no-browser --timeout 120 ./studyThe command follows the same VS Code routing rule as view(), waits for the viewer to exit, and returns its exit code.
Handle failures
Section titled “Handle failures”ValueError: no paths were supplied.TypeError: a file, annotation, or filter value has the wrong type, or a removed keyword such astunnelwas passed.RuntimeError: no usable binary was found.subprocess.CalledProcessError: the viewer exited with a non-zero status or found no files. The exception carries the viewer’s last output.
To inspect remote data, run view() with browser=False on the remote machine, forward the port from your local machine, and open the printed http://localhost:PORT/#token=… link with its token fragment, as described in Inspect a study over SSH. view() does not offer the private --unix-socket mode; use the dcmview command for that.
Read the exact Python API reference for every parameter, binary resolution, and bridge environment variable.