Global variables

There are cases where you might want objects or data available in global scope. For example:

  • You need to use the data in a scheduled function (scheduled functions don’t accept arguments)
  • You need to construct objects (e.g. Secrets) in global scope to use as function annotations
  • You don’t want to clutter many function signatures with some common arguments they all use, and pass the same arguments through many layers of function calls.

For these cases, you can use the modal.is_local function, which returns True if the app is running locally (initializing) or False if the app is executing in the cloud.

For instance, you can use a modal.Dict object to store one or multiple objects by key (similar to a Python dict) for later access in Modal functions:

import json
import random

if modal.is_local():
    with open("list.json", "r") as f:
        foo_list = json.load(f)  # reads from local disk on the development machine
    stub["data_dict"] = modal.Dict({"foo": foo_list})


@stub.function(schedule=modal.Period(days=1))
def daily_random_entry():
    print(random.choice(modal.container_app["data_dict"]["foo"]))

Similarly, to create a modal.Secret that you can pass to your function decorators to create environment variables, you can run:

import os

if modal.is_local():
    stub["password"] = modal.Secret({"PGPASS": os.environ["MY_LOCAL_PASSWORD"]})


@stub.function(secret=stub["password"])
def get_secret_data():
    connection = psycopg2.connect(password=os.environ["PGPASS"])
    ...

Warning about regular module globals

If you try to construct a global in module scope using some local data without using something like modal.is_local, it might have unexpected effects since your Python modules will be not only be loaded on your local machine, but also on the remote worker.

E.g., this will typically not work:

# blob.json doesn't exist on the remote worker, so this will cause an error there
data_blob = open("blob.json", "r").read()

@stub.function
def foo():
    print(data_blob)