Skip to main content

Python client for the Ray debugging app (port of spatie/ray PHP library)

Project description

Python client for Ray

Python client library for the Ray desktop debugging tool.

Use it to send rich debug information (logs, tables, traces, exceptions, etc.) from Python into Ray with a single ray(...) call, mirroring the behavior of the original PHP client.

Repository: https://github.com/axro-gmbh/ray

Installation

From PyPI (recommended)

Once the package is published, install it in your project with:

pip install ray-python

Then in your code:

from python_ray import ray

ray("Hello from Python Ray")

From a local checkout (development)

From the root of this repository:

pip install -e .[dev]

This installs the python_ray package in editable mode so changes in this repo are immediately reflected.

Requirements

  • Ray desktop app installed and running on your machine (default host/port: localhost:23517).
  • Python 3.13+ (see requires-python in pyproject.toml).

Versioning & compatibility

  • This library targets modern CPython and is currently tested with Python 3.13.
  • The requires-python metadata is set to >=3.13; earlier Python versions are not supported.

Configuration (ray.json)

The Python client looks for a ray.json file starting from the current working directory and walking up parent directories (similar to how the PHP client searches for ray.php).

Example ray.json:

{
  "enable": true,
  "host": "localhost",
  "port": 23517,
  "remote_path": null,
  "local_path": null,
  "always_send_raw_values": false
}

Available keys:

  • enable (bool): if false, nothing is sent to Ray.
  • host (str): Ray server host (defaults to localhost).
  • port (int): Ray server port (defaults to 23517).
  • remote_path (str|null): remote path prefix to be rewritten in file paths (for origins, traces, etc.).
  • local_path (str|null): local path prefix that replaces remote_path when sending paths.
  • always_send_raw_values (bool): if true, ray(...) always sends values as raw log payloads (no type-based conversion).

If no ray.json is found, sensible defaults are used.

Quick start

Basic usage:

from python_ray import ray

# Simple values
ray("hello")
ray({"foo": "bar"}, 123)

# Chain on the Ray instance
ray("starting").green().label("Init")

Core features

Below are some commonly used features. All examples assume:

from python_ray import ray

Screens and layout

ray().new_screen("Job 1")
ray().clear_all()        # clear everything
ray().clear_screen()     # alias for new_screen("")
ray().separator()        # horizontal separator

Colors, sizes, labels

ray("success").green()
ray("warning").orange()
ray("error").red()

ray("big").large()
ray("small").small()

ray("labeled").label("My label")

Files, images, XML, HTML, URLs

ray().file("README.md")
ray().image("screenshot.png")
ray().xml("<root><item>42</item></root>")
ray().html("<strong>Bold</strong>")
ray().url("https://example.com", "Example")

JSON helpers

# send values encoded with json.dumps
ray().to_json({"a": 1}, [1, 2, 3])

# send decoded JSON strings
ray().json('{"a": 1}', '[1, 2, 3]')

Python runtime info

# high-level summary
ray().pythoninfo()

# specific properties
ray().pythoninfo("version", "implementation")

Traces and caller

ray().trace()              # full-ish Python stack trace (user frames)
ray().trace(limit=10)      # first 10 frames
ray().backtrace()          # alias for trace()
ray().caller()             # single caller frame

Timers (measure / stop_time)

ray().measure("block")
# ... some code ...
ray().measure("block")    # sends total + since-last-call
ray().stop_time("block")  # clear this timer
ray().stop_time()          # clear all timers

Counters

ray().count()               # per-call-site counter
ray().count("my-counter")   # named counter
value = ray().counter_value("my-counter")
ray().clear_counters()

Flow control and rate limiting

r = ray("maybe")
if some_flag:
    r.enable()
else:
    r.disable()

ray().limit(3).send("only three times from here")
ray().once("only once from here")

ray("waiting").pause()  # creates a lock in Ray; resumes when released there

Exceptions and catch / throw_exceptions

You can pass callables into send() that accept a Ray instance; any exceptions they raise are captured instead of crashing immediately.

from python_ray import ray

def might_fail(r):
    1 / 0

ray().send(might_fail)   # exception is stored in Ray._caught_exceptions

# Show in Ray:
ray().catch()            # uses Ray.exception() under the hood

# Filter by type:
ray().catch(ZeroDivisionError)

# Or rethrow:
ray().throw_exceptions()

You can also directly send exceptions:

try:
    expensive_call()
except Exception as exc:
    ray().exception(exc)

Conditionals and removal helpers

# Only send when condition holds
ray().if_(lambda: user.is_admin).send("admin only")

# Or provide a callback to run when condition is true
ray().if_(user.is_admin, lambda r: r.green().text("admin"))

# Deprecated-style helpers (still provided):
ray("maybe").show_when(lambda: condition)
ray("maybe").remove_when(lambda: should_hide)

Working with objects (JSON + introspection)

ray().object(obj) tries to convert arbitrary Python objects into JSON and send a pretty-printed JSON string to Ray/Buggregator.

It will try, in order:

  • dataclasses.asdict(obj) for dataclasses,
  • obj.model_dump() for Pydantic v2 models,
  • obj.dict() for Pydantic v1 / similar APIs,
  • public attributes from obj.__dict__ (filtering out private names starting with _).

If conversion or JSON serialization fails, it falls back to repr(obj).

user = get_user() ray().object(user)


`invade()` lets you inspect attributes and method results without changing your code too much:

```python
class User:
    def __init__(self):
        self._password = "secret"
    def full_name(self):
        return "Ada Lovelace"

user = User()

ray().invade(user)._password        # sends the value of _password
ray().invade(user).full_name()      # calls method and sends result

Using from another local project

If you have another local project and want to use this Python client without publishing to PyPI yet, you can install from the path to this repo:

pip install -e /path/to/ray[dev]

Then in that other project:

from python_ray import ray

ray("from another project")

As long as the Ray desktop app is running and configuration (if any) is correct, you should see messages in Ray.

Contributing

Bug reports and pull requests are welcome at https://github.com/axro-gmbh/ray.

For Python changes, please keep the public API of python_ray aligned with the original PHP Ray client where it makes sense, and update the README and pyproject.toml when behavior or supported Python versions change.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ray_python-1.0.0.tar.gz (28.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ray_python-1.0.0-py3-none-any.whl (36.4 kB view details)

Uploaded Python 3

File details

Details for the file ray_python-1.0.0.tar.gz.

File metadata

  • Download URL: ray_python-1.0.0.tar.gz
  • Upload date:
  • Size: 28.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ray_python-1.0.0.tar.gz
Algorithm Hash digest
SHA256 b10d08fc876d9d6239891f7cde3ab0d32a39639bba21c331f0eaccd593aed59e
MD5 db4b3cfdddeaf96d92313b114619b7c7
BLAKE2b-256 cbaf0cd917099861a5d36ded4ef363e79ae073512f9887d1d738d46134b6e79a

See more details on using hashes here.

File details

Details for the file ray_python-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: ray_python-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 36.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ray_python-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2ca205b9f0b606d6716b4c46187354113aa84d4ad21ba7de525929ddc4c6555d
MD5 67406a36ac244dfa7a7f4d30bab4cf0d
BLAKE2b-256 8d4214e0e035fbe5758b2ff268f88f9a5a12f978b55df2a860a796baa900c41f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page