modal.functions
modal.functions.Function
class Function(modal.object.Provider)
Functions are the basic units of serverless execution on Modal.
Generally, you will not construct a Function
directly. Instead, use the
@stub.function
decorator on the Stub
object for your application.
persist
@typechecked
def persist(self, label: str, namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE):
Deploy a Modal app containing this object. This object can then be imported from other apps using
the returned reference, or by calling modal.SharedVolume.from_name(label)
(or the equivalent method
on respective class).
Example Usage
import modal
volume = modal.SharedVolume().persist("my-volume")
stub = modal.Stub()
# Volume refers to the same object, even across instances of `stub`.
@stub.function(shared_volumes={"/vol": volume})
def f():
pass
from_name
@classmethod
def from_name(
cls: Type[P], app_name: str, tag: Optional[str] = None, namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE
) -> P:
Returns a reference to an Modal object of any type
Useful for referring to already created/deployed objects, e.g., Secrets
import modal
stub = modal.Stub()
@stub.function(secret=modal.Secret.from_name("my-secret-name"))
def some_function():
pass
lookup
@classmethod
def lookup(
cls: Type[P],
app_name: str,
tag: Optional[str] = None,
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
client: Optional[_Client] = None,
) -> H:
General purpose method to retrieve Modal objects such as functions, shared volumes, and secrets.
import modal
square = modal.Function.lookup("my-shared-app", "square")
assert square(3) == 9
vol = modal.SharedVolume.lookup("my-shared-volume")
for chunk in vol.read_file("my_db_dump.csv"):
...
get_panel_items
def get_panel_items(self) -> List[str]:
modal.functions.FunctionCall
class FunctionCall(modal.object.Handle)
A reference to an executed function call
Constructed using .spawn(...)
on a Modal function with the same
arguments that a function normally takes. Acts as a reference to
an ongoing function call that can be passed around and used to
poll or fetch function results at some later time.
Conceptually similar to a Future/Promise/AsyncResult in other contexts and languages.
def __init__(self):
from_id
@classmethod
def from_id(cls: Type[H], object_id: str, client: Optional[_Client] = None) -> H:
Get an object of this type from a unique object id (retrieved from obj.object_id
)
object_id
@property
def object_id(self) -> str:
A unique object id for this instance. Can be used to retrieve the object using .from_id()
from_app
@classmethod
def from_app(
cls: Type[H],
app_name: str,
tag: Optional[str] = None,
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
client: Optional[_Client] = None,
) -> H:
Returns a handle to a tagged object in a deployment on Modal.
get
def get(self, timeout: Optional[float] = None):
Gets the result of the function call
Raises TimeoutError
if no results are returned within timeout
seconds.
Setting timeout
to None (the default) waits indefinitely until there is a result
get_call_graph
def get_call_graph(self) -> List[InputInfo]:
Returns a nested dictionary structure representing the call graph from a given root call ID, along with the status of execution for each node.
cancel
def cancel(self):
modal.functions.FunctionHandle
class FunctionHandle(modal.object.Handle)
Interact with a Modal Function of a live app.
def __init__(self):
from_id
@classmethod
def from_id(cls: Type[H], object_id: str, client: Optional[_Client] = None) -> H:
Get an object of this type from a unique object id (retrieved from obj.object_id
)
object_id
@property
def object_id(self) -> str:
A unique object id for this instance. Can be used to retrieve the object using .from_id()
from_app
@classmethod
def from_app(
cls: Type[H],
app_name: str,
tag: Optional[str] = None,
namespace=api_pb2.DEPLOYMENT_NAMESPACE_WORKSPACE,
client: Optional[_Client] = None,
) -> H:
Returns a handle to a tagged object in a deployment on Modal.
web_url
@property
def web_url(self) -> str:
URL of a Function running as a web endpoint.
is_generator
@property
def is_generator(self) -> bool:
map
@warn_if_generator_is_not_consumed
def map(
self,
*input_iterators, # one input iterator per argument in the mapped-over function/generator
kwargs={}, # any extra keyword arguments for the function
order_outputs=None, # defaults to True for regular functions, False for generators
return_exceptions=False, # whether to propogate exceptions (False) or aggregate them in the results list (True)
):
Parallel map over a set of inputs.
Takes one iterator argument per argument in the function being mapped over.
Example:
@stub.function
def my_func(a):
return a ** 2
assert list(my_func.map([1, 2, 3, 4])) == [1, 4, 9, 16]
If applied to a stub.function
, map()
returns one result per input and the output order
is guaranteed to be the same as the input order. Set order_outputs=False
to return results
in the order that they are completed instead.
If applied to a stub.generator
, the results are returned as they are finished and can be
out of order. By yielding zero or more than once, mapping over generators can also be used
as a “flat map”.
return_exceptions
can be used to treat exceptions as successful results:
@stub.function
def my_func(a):
if a == 2:
raise Exception("ohno")
return a ** 2
# [0, 1, UserCodeException(Exception('ohno'))]
print(list(my_func.map(range(3), return_exceptions=True)))
for_each
def for_each(self, *input_iterators, kwargs={}, ignore_exceptions=False):
Execute function for all outputs, ignoring outputs
Convenient alias for .map()
in cases where the function just needs to be called.
as the caller doesn’t have to consume the generator to process the inputs.
starmap
@warn_if_generator_is_not_consumed
def starmap(self, input_iterator, kwargs={}, order_outputs=None, return_exceptions=False):
Like map
but spreads arguments over multiple function arguments
Assumes every input is a sequence (e.g. a tuple).
Example:
@stub.function
def my_func(a, b):
return a + b
assert list(my_func.starmap([(1, 2), (3, 4)])) == [3, 7]
call
def call(self, *args, **kwargs):
Calls the function, executing it remotely with the given arguments and returning the execution’s result.
spawn
def spawn(self, *args, **kwargs) -> Optional["_FunctionCall"]:
Calls the function with the given arguments, without waiting for the results.
Returns a modal.functions.FunctionCall
object, that can later be polled or waited for using .get(timeout=...)
.
Conceptually similar to multiprocessing.pool.apply_async
, or a Future/Promise in other contexts.
Note: .spawn()
on a modal generator function does call and execute the generator, but does not currently
return a function handle for polling the result.
get_raw_f
def get_raw_f(self) -> Callable:
Return the inner Python object wrapped by this Modal Function.
get_current_stats
def get_current_stats(self) -> FunctionStats:
Return a FunctionStats
object describing the current function’s queue and runner counts.
modal.functions.FunctionStats
class FunctionStats(object)
Simple data structure storing stats for a running function.
def __init__(self, backlog: int, num_active_runners: int, num_total_runners: int) -> None
modal.functions.current_input_id
def current_input_id() -> str:
Returns the input ID for the currently processed input.
Can only be called from Modal function (i.e. in a container context).
from modal import current_input_id
@stub.function
def process_stuff():
print(f"Starting to process {current_input_id()}")
modal.functions.gather
def gather(*function_calls: _FunctionCall):
Wait until all Modal function calls have results before returning
Accepts a variable number of FunctionCall objects as returned by Function.spawn()
.
Returns a list of results from each function call, or raises an exception of the first failing function call.
E.g.
function_call_1 = slow_func_1.spawn()
function_call_2 = slow_func_2.spawn()
result_1, result_2 = gather(function_call_1, function_call_2)