When you need to run data processing or machine learning tasks in a distributed environment, a Ray application provides an efficient way to submit and manage your Python jobs. This document explains how to submit a job to your Ray application using various methods, including JupyterLab, the Python SDK, and the CLI. You will also learn how to monitor job status and view results to simplify your development and deployment workflows.
Comparison of methods
A Ray application offers multiple methods for job submission. Choose the one that best suits your use case and preferences.
|
Method |
Use case |
Pros |
Cons/Notes |
|
JupyterLab Terminal (Recommended) |
Quickly submitting and testing scripts in a console environment. |
No local configuration is required. The environment is pre-installed and ready to use. |
Not suitable for automated or large-scale submissions. |
|
Jupyter Notebook (Recommended) |
Interactive data exploration and algorithm debugging. |
Highly interactive, allowing for line-by-line execution and easier debugging. |
Resources are tied to the session, making it unsuitable for long-running production tasks. |
|
Ray Python SDK (Recommended) |
Local development, integration with existing Python applications, and CI/CD automation. |
Flexible, powerful, and easy to integrate. |
Requires installing |
|
Ray CLI (Local/ECS) |
For developers who prefer using the native Ray CLI for scripted submissions. |
Provides an experience similar to native Ray. |
Configuration is similar to the Python SDK but offers slightly less flexibility. |
|
REST API (Not recommended) |
Specific automation scenarios, such as making calls from a non-Python environment. |
Language-agnostic with minimal dependencies. |
Limited functionality. Cannot automatically upload code packages, and the call process is cumbersome. |
Before you begin
Before submitting a job, obtain the connection address and configuration information from your Ray application and add the private IP address or public IP address of your development environment to the application whitelist.
Submit a job using the JupyterLab Terminal
This method uses the ray job submit command in the pre-configured environment provided by the Ray application. It requires no local dependencies and is the recommended way to quickly test and run scripts.
When you submit a job using the JupyterLab Terminal, you must also add the VPC primary IPv4 CIDR block of the cluster where the Ray application resides to the application whitelist.
-
Log on to JupyterLab:
-
Open the Jupyter public URL in your browser.
-
In the Password or token field, enter the key for
secret.jupyterlab.passwordto access the JupyterLab interface.
-
-
Prepare a Python script:
-
In the JupyterLab file browser, create a working directory (for example,
src). To upload project files (such as asrcdirectory andrequirements.txt), click the upload icon to the right of the + icon in the file browser toolbar. To create a new Python script file (for example,script.py), open the Launcher and click Python File in the Other section. -
Example
src/script.pycontent:import ray import time @ray.remote def retrieve_task(item, db): time.sleep(item / 10.) return item, db[item] if __name__ == "__main__": database = [ "Learning", "Ray", "Flexible", "Distributed", "Python", "for", "Machine", "Learning" ] ray.init() db_object_ref = ray.put(database) retrieve_refs = [ retrieve_task.remote(item, db_object_ref) for item in [0, 2, 4, 6] ] result = [print(data) for data in ray.get(retrieve_refs)]
-
-
Submit the job and view the results:
-
In JupyterLab, open a new terminal by selecting and then clicking Terminal.
-
In the terminal, run the following commands to submit the job and view its logs.
# 1. Return to the parent directory to demonstrate using the --working-dir parameter. cd .. # 2. Set the environment variable. Replace the placeholder with your actual key. # Anonymous key for job submission: secret.jwt.anonKey ANON_KEY="<YOUR_ANON_KEY>" # 3. Submit the job. # Submit the job and wait for the result. ray job submit --headers "{\"Authorization\": \"Bearer $ANON_KEY\"}" --working-dir ./src -- python script.py # Submit the job without waiting for the result. ray job submit --headers "{\"Authorization\": \"Bearer $ANON_KEY\"}" --no-wait --working-dir ./src -- python script.pyExample output:
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: http://xxx/api/version (base) jovyan@pa-xxx:~/work$ ANON_KEY="exxx" Yxxx (base) jovyan@pa-2xxx:~/work$ ray job submit --headers "{\"Authorization\": \"Bearer $ANON_KEY\"}" --no-wait --working-dir ./src -- python script.py Job submission server address: http://1xxx:8265 2025-12-18 03:47:06,460 INFO dashboard_sdk.py:338 -- Uploading package gcs://_ray_pkg_xxx.zip. 2025-12-18 03:47:06,461 INFO packaging.py:576 -- Creating a file package for local module './src'. ------------------------------------------------------- Job 'raysubmit_Jxxx' submitted successfully ------------------------------------------------------- Next steps Query the logs of the job: ray job logs raysubmit_Jxxx Query the status of the job: ray job status raysubmit_xxx Request the job to be stopped: ray job stop raysubmit_Jxxx (base) jovyan@pa-xxx:~/work$
-
Run interactive jobs in Jupyter Notebook
Jupyter Notebook is ideal for scenarios that require line-by-line code execution, exploratory analysis, and debugging.
-
Log on and create a notebook:
-
Open the Jupyter public URL in your browser.
-
In the **Password or token** field, enter the key corresponding to
secret.jupyterlab.passwordto access the JupyterLab interface. -
Open the Launcher by selecting . The Launcher page provides three Python development options: click Python 3 (ipykernel) in the Notebook section to create an interactive notebook; click Python 3 (ipykernel) in the Console section to open an interactive console; or click Python File in the Other section to create a Python script file.
-
-
Run the code: Enter and run the following code in a code cell.
import ray import time @ray.remote def retrieve_task(item, db): time.sleep(item / 10.) return item, db[item] if __name__ == "__main__": database = [ "Learning", "Ray", "Flexible", "Distributed", "Python", "for", "Machine", "Learning" ] ray.init() db_object_ref = ray.put(database) retrieve_refs = [ retrieve_task.remote(item, db_object_ref) for item in [0, 2, 4, 6] ] result = [print(data) for data in ray.get(retrieve_refs)]The output is as follows:
(0, 'Learning') (2, 'Flexible') (4, 'Python') (6, 'Machine')
Submit a job using the Ray Python SDK
Use the Ray Python SDK when you need to programmatically submit jobs from your local development environment, an existing Python application, or a CI/CD pipeline.
-
Prepare the environment
NoteEnsure that a Python 3 environment is installed on your local machine.
Install the Ray SDK:
pip install ray -
Prepare the code files
In your working directory, create two Python scripts: one for your business logic and one for submitting the job. The directory structure should look like this:- working-dir/ - script.py # Your Ray business logic script - ray_job_submit.py # Script for submitting the jobscript.pyimport ray import time @ray.remote def retrieve_task(item, db): time.sleep(item / 10.) return item, db[item] if __name__ == "__main__": database = [ "Learning", "Ray", "Flexible", "Distributed", "Python", "for", "Machine", "Learning" ] ray.init() db_object_ref = ray.put(database) retrieve_refs = [ retrieve_task.remote(item, db_object_ref) for item in [0, 2, 4, 6] ] result = [print(data) for data in ray.get(retrieve_refs)]ray_job_submit.pyimport os import json import base64 import hmac import hashlib import requests from datetime import timezone, timedelta, datetime from requests.auth import HTTPBasicAuth from ray.job_submission import JobSubmissionClient # Your Ray Dashboard address address = os.getenv("RAY_DASHBOARD_ADDRESS") # Authenticate directly using secret.jwt.anonKey. token = os.getenv("RAY_ANON_TOKEN") # Alternatively, generate a JWT using secret.jwt.secret. secret = os.getenv("RAY_JWT_SECRET") header = {"alg": "HS256", "typ": "JWT"} now = datetime.now(tz=timezone.utc) payload = { "sub": "anon", "iat": int(now.timestamp()), "exp": int((now + timedelta(hours=12)).timestamp()), "iss": "ray-dashboard", "aud": "ray-dashboard-client" } header_encoded = base64.urlsafe_b64encode( json.dumps(header, separators=(',', ':')).encode()).decode('utf-8').rstrip('=') payload_encoded = base64.urlsafe_b64encode( json.dumps(payload, separators=(',', ':')).encode()).decode('utf-8').rstrip('=') message = f"{header_encoded}.{payload_encoded}" signature = hmac.new(secret.encode(), message.encode(), hashlib.sha256).digest() signature_encoded = base64.urlsafe_b64encode(signature).decode('utf-8').rstrip( '=') token = f"{message}.{signature_encoded}" # You can also obtain a JWT by sending a POST request to /api/auth/token. You need to provide a username and password. username = os.getenv('RAY_USERNAME') password = os.getenv('RAY_PASSWORD') response = requests.post(f'{address}/api/auth/token', auth=HTTPBasicAuth(username, password), timeout=5) if response.status_code == 200: token_data = response.json() token = token_data['access_token'] else: print(f"Failed to get JWT: {response.status_code}") client = JobSubmissionClient(address, headers={"Authorization": f"Bearer {token}"}) job_id = client.submit_job( # Entrypoint shell command to execute entrypoint="python script.py", # Path to the local directory that contains the script.py file runtime_env={"working_dir": "./"}) print(job_id) -
Configure and run
-
Find the required values on the Configuration Information page of your Ray application, and set them as environment variables or replace the placeholders in the
ray_job_submit.pyscript.Parameter
Configuration item
Example
RAY_DASHBOARD_ADDRESSThe connection address of the Ray application. Choose the public or private address based on your environment.
http://123.xxx.xxx.xxx:8265RAY_ANON_TOKENsecret.jwt.anonKeyeyJhbGciOi...RAY_JWT_SECRETsecret.jwt.secrettNhVxysSRD...RAY_USERNAMEsecret.dashboard.usernameadminRAY_PASSWORDsecret.dashboard.passwordUTLof$rMVM... -
In your working directory, run the submission script:
python ray_job_submit.py -
After the script runs successfully, log in to the Ray Dashboard and navigate to the Jobs page to view the status of the submitted job. Verify that the job record shows an Entrypoint of
python script.py, a Status of SUCCEEDED, and a Status message ofJob finished successfully, which indicates that the job has completed.
-
Submit a job with the Ray CLI
This method is similar to using the JupyterLab Terminal but is executed from your own environment. It is suitable for developers who prefer the command line.
-
Prerequisites
-
Network: Ensure your development environment's IP address is in the application's whitelist or security group and has access to the Ray Dashboard address.
-
To install Ray, run
pip install ray.
-
-
Submit the job: In your local terminal or ECS Terminal, use the
ray job submitcommand. You must specify the Ray Dashboard address for all commands using the--addressparameter.# Set environment variables. Replace the placeholders with your actual values. # The Ray Dashboard address for the application. It must be prefixed with http://. RAY_ADDRESS="<YOUR_DASHBOARD_URL>" # Anonymous key for job submission: secret.jwt.anonKey ANON_KEY="<YOUR_ANON_KEY>" # Submit the job ray job submit --address "$RAY_ADDRESS" --headers "{\"Authorization\": \"Bearer $ANON_KEY\"}" --working-dir <path_to_your_working_dir> -- python script.py
Submit a job using the REST API
This method is intended only for running simple, single-line commands. It cannot automatically upload local Python scripts or code directories. For most use cases, we recommend the more powerful and convenient Ray Python SDK or Ray CLI.
-
Prepare request information: Obtain the Ray Dashboard and the anonymous key
secret.jwt.anonKey. -
Send a POST request: Use
curlor an HTTP client in any programming language to send the request. The following example uses Python:import requests import json # Your Ray Dashboard address. It must be prefixed with http://. RAY_ADDRESS = "<YOUR_DASHBOARD_URL>" # Your anonymous key. RAY_ANON_KEY = "<YOUR_ANON_KEY>" headers = { 'Content-Type': 'application/json', "Authorization": f"Bearer {RAY_ANON_KEY}" } # The entrypoint can only be a simple, single-line command. payload = { "entrypoint": "python -c \"import ray; ray.init(); print(ray.nodes())\"", } # The API endpoint must end with a forward slash ("/"). response = requests.post( f"{RAY_ADDRESS}/api/jobs/", json=payload, headers=headers ) response.raise_for_status() job_info = response.json() print(f"Job submitted successfully: {job_info}")The output is as follows:
Job submitted successfully: {'job_id': 'raysubmit_xxx', 'submission_id': 'raysubmit_xxx'}