Skip to main content
Ces exemples utilisent un jeton d’accès à l’API CoreWeave défini dans CWSANDBOX_API_KEY. Pour l’authentification par clé API Forge, consultez Premiers pas. Pour les exigences relatives à CKS, consultez Modes de placement. Ce guide décrit les étapes que traverse une sandbox, de sa création à son arrêt : les états par lesquels elle passe, comment la démarrer et attendre qu’elle soit prête, et comment l’arrêter proprement. Consultez-le lorsque vous devez choisir entre plusieurs modèles de création, maîtriser le moment du démarrage ou gérer l’arrêt de manière fiable dans votre code SDK.

États du cycle de vie

Chaque sandbox passe par une succession d’états au cours de son démarrage, de son exécution et de son arrêt. Le SDK représente ces états sous forme de valeurs SandboxStatus. PENDING et CREATING sont transitoires. Le SDK poursuit automatiquement l’interrogation pendant ces états. TERMINATING est un état transitoire du backend que wait_until_complete() et stop().result() font évoluer jusqu’à un état terminal. RUNNING est l’état opérationnel stable. COMPLETED et FAILED sont terminaux. Lors de l’interrogation, le SDK convertit UNSPECIFIED en COMPLETED.

Modèles de création

Il existe deux façons de créer une sandbox, qui se distinguent par le moment où la RPC de démarrage est déclenchée. Les sections suivantes décrivent chaque modèle et indiquent dans quels cas le choisir.

Sandbox.run() : démarrage immédiat

Sandbox.run() crée une sandbox et appelle start().result() en interne, puis reste bloqué jusqu’à ce que le backend accepte la requête :
Le premier argument positionnel est la commande ; les suivants sont ses arguments :

session.sandbox() : démarrage différé

session.sandbox() crée un objet sandbox sans effectuer le moindre appel réseau. Le RPC de démarrage se déclenche à la première utilisation :

Durée de vie de la commande principale

La commande transmise à run() ou à session.sandbox() constitue le processus principal de la sandbox. Ce qui se passe lorsqu’elle se termine dépend de son statut de sortie :
  • Statut de sortie 0 : la sandbox passe à l’état COMPLETED.
  • Statut de sortie non nul : la plateforme redémarre le conteneur du processus principal. Une sandbox qui a déjà atteint l’état RUNNING reste à l’état RUNNING pendant les redémarrages ; sinon, elle reste à l’état CREATING. wait_until_complete() continue d’attendre pendant les redémarrages, dans la limite de son timeout.
  • Limite de redémarrages atteinte : si le processus principal continue de se terminer avec un statut non nul, la sandbox passe à l’état FAILED une fois la limite de redémarrages atteinte (actuellement six redémarrages).
Un processus principal qui se termine avec succès met fin à la sandbox :
Si vous devez exécuter une commande courte et capturer sa sortie, utilisez exec() sur une sandbox de longue durée plutôt que d’en faire le processus principal.

Démarrer un sandbox

Une fois l’objet sandbox créé, vous pouvez le démarrer explicitement ou laisser le SDK le démarrer automatiquement lors de sa première utilisation. Les sections suivantes décrivent ces deux approches, ainsi que leur interaction avec les gestionnaires de contexte.

Démarrage explicite

start() envoie la RPC de démarrage et renvoie un OperationRef[None] :
C’est utile lorsque vous souhaitez contrôler le moment du démarrage ou traiter les erreurs de démarrage séparément des erreurs d’opération.

Démarrage automatique

La plupart des opérations démarrent automatiquement la sandbox si elle n’a pas encore été démarrée. Dans le cas le plus courant, il vous suffit de créer une sandbox et de commencer à l’utiliser.

Gestionnaires de contexte et démarrage

Les gestionnaires de contexte (with/async with) appellent start() à l’entrée, mais n’appellent pas wait(). Si la sandbox doit être à l’état RUNNING avant votre première opération, appelez explicitement wait() :
En pratique, cela a rarement d’importance, car exec() attend en interne l’état RUNNING. Un appel explicite à wait() est utile lorsque vous souhaitez distinguer les échecs au démarrage des échecs d’opération.

Attendre une sandbox

Le SDK fournit deux méthodes d’attente, selon que vous avez besoin que la sandbox soit prête à exécuter des opérations ou qu’elle termine sa commande principale. Les sections suivantes décrivent chaque méthode et expliquent le lien entre les délais d’expiration de démarrage et ceux des opérations.

wait() : bloquer jusqu’à l’état RUNNING

wait() interroge l’état de la sandbox jusqu’à ce qu’elle atteigne l’état RUNNING, TERMINATING ou un état terminal :
L’interrogation applique un backoff exponentiel : elle commence avec des intervalles de 0,2 s, multipliés par 1,5 à chaque tentative, avec un plafond de 2,0 s. wait() renvoie self, ce qui permet le chaînage de méthodes :
Si la sandbox atteint un état terminal pendant le démarrage, wait() le gère ainsi :

wait_until_complete() : bloquer jusqu’à un état terminal

wait_until_complete() bloque jusqu’à ce que la sandbox atteigne un état terminal, en continuant automatiquement d’interroger son état pendant la phase TERMINATING. Utilisez cette méthode pour les Sandbox dont la commande principale effectue le travail :
Le paramètre raise_on_termination, défini sur True par défaut, détermine si wait_until_complete() lève SandboxTerminatedError lorsque ce client a appelé stop(). Les arrêts externes apparaissent comme COMPLETED, sans erreur distincte, car le backend ne fournit pas encore de métadonnées sur le motif de l’arrêt. En revanche, une sandbox qui atteint sa durée de vie maximale se termine à l’état FAILED, et wait_until_complete() lève alors SandboxFailedError.

Phases des délais d’expiration

Le temps d’attente au démarrage et les délais d’expiration des opérations sont deux phases distinctes, toutes deux bornées par la durée de vie maximale de la sandbox :
  • Attente de démarrage : temps passé dans les états PENDING/CREATING avant d’atteindre l’état RUNNING. Contrôlée par le paramètre timeout de wait() ou wait_until_complete(). Généralement de 30 à 60 secondes selon l’ordonnancement du backend.
  • Délai d’expiration des opérations : durée allouée à chaque exécution, lecture ou écriture. Contrôlé par timeout_seconds sur exec(), ou par request_timeout_seconds dans SandboxDefaults. N’inclut pas l’attente de démarrage.
  • Durée de vie maximale : durée totale (temps réel) pendant laquelle la sandbox peut exister, comptée à partir du démarrage, attente de démarrage comprise. Contrôlée par max_lifetime_seconds. Si vous ne la définissez pas, la valeur par défaut de la politique de l’exécuteur s’applique ; à défaut de valeur par défaut positive, la plateforme applique une valeur de repli de 10 minutes.
L’attente de démarrage et les délais d’expiration des opérations limitent la durée d’attente du client, mais laissent la sandbox s’exécuter lorsqu’ils expirent. La durée de vie maximale limite la sandbox elle-même : à son expiration, la plateforme met fin à la sandbox et toute opération en cours échoue en même temps. Attribuez à max_lifetime_seconds une valeur largement supérieure à la durée totale de travail prévue. Vous ne pouvez plus la modifier une fois la sandbox démarrée. Pour découvrir les quatre paramètres de délai d’expiration et leurs interactions, consultez Délais d’expiration. Pour la limite de 30 jours et des exemples de configuration pour Serverless et CKS, consultez Exécuter des Sandbox de longue durée.

Opérations et cycle de vie

Les opérations telles que exec(), read_file() et write_file() démarrent automatiquement la sandbox si nécessaire, puis attendent l’état RUNNING avant de continuer :
Le délai d’expiration de l’opération (timeout_seconds) ne s’applique qu’une fois la sandbox à l’état RUNNING. Le temps de démarrage n’est pas pris en compte.

Arrêter une sandbox et fin de vie

Cette section explique comment arrêter une sandbox, ce qui se passe après son arrêt et quand utiliser stop() plutôt que delete().

stop()

stop() envoie une requête d’arrêt et renvoie OperationRef[None]. Le sandbox passe par l’état TERMINATING (drainage pendant le délai de grâce) avant d’atteindre un état terminal. L’OperationRef renvoyé est résolu lorsque le backend confirme l’état terminal, et non simplement lorsque l’appel RPC d’arrêt aboutit :
Paramètres :
stop() gère les démarrages en cours : si un démarrage est encore en cours de traitement, la méthode attend qu’il se termine avant de procéder à l’arrêt. Les appels simultanés ou répétés à stop() partagent une seule opération d’arrêt et n’émettent pas de RPC d’arrêt en double. Vous pouvez donc appeler stop() plusieurs fois sans risque et à moindre coût.

Comportement après l’arrêt

Une fois stop() appelé, la sandbox passe par l’état TERMINATING (état de drainage pendant le délai de grâce) puis atteint un état terminal (COMPLETED ou FAILED). Dès que stop() a été appelé, la sandbox devient inutilisable. Toute opération ultérieure lève SandboxNotRunningError :
La propriété status est mise en cache lors du dernier appel d’API. Pour obtenir des données à jour avant l’arrêt, utilisez get_status() :

Sortie du gestionnaire de contexte

Les gestionnaires de contexte appellent automatiquement stop() à leur sortie :
Si une exception est en cours de propagation, le gestionnaire de contexte ignore les erreurs d’arrêt afin de ne pas masquer l’exception d’origine.

stop() ou delete()

Utilisez stop() pour les Sandbox que vous êtes en train d’utiliser. Utilisez delete() pour nettoyer les Sandbox trouvées via Sandbox.list() ou Sandbox.from_id() :
Voir le guide des modèles de nettoyage pour connaître les stratégies de gestion des ressources orphelines et de nettoyage par lots.

Fonctionnement interne

Le SDK exécute toutes les opérations gRPC sur un thread démon en arrière-plan, doté de sa propre boucle d’événements asyncio. Cette conception a les conséquences suivantes :
  • L’API synchrone (.result()) bloque le thread appelant pendant que la boucle en arrière-plan gère l’appel réseau.
  • L’API asynchrone (await) s’appuie sur cette même boucle en arrière-plan : les deux modèles reposent donc sur la même implémentation sous-jacente.
  • La boucle en arrière-plan démarre de manière différée, lors de la première utilisation. Les canaux gRPC sont eux aussi créés de manière différée.
  • Le démarrage automatique consiste à vérifier si sandbox_id vaut None avant chaque opération et, le cas échéant, à déclencher start().
  • À la fin du processus, les handlers de nettoyage (atexit + handlers de signaux) arrêtent tous les Sandbox des sessions enregistrées. Un second Ctrl+C pendant le nettoyage force l’arrêt immédiat.
Cette architecture évite les problèmes liés à l’utilisation de plusieurs boucles d’événements et fonctionne dans les notebooks Jupyter sans nest_asyncio. Pour connaître les modèles d’utilisation, consultez le guide comparant les modèles synchrone et asynchrone.

Schémas courants

Les exemples suivants illustrent des schémas de bout en bout qui combinent les étapes du cycle de vie décrites ci-dessus.

Exécution ponctuelle rapide

Exécutez une commande et récupérez le résultat. Le gestionnaire de contexte se charge du nettoyage :

Démarrage contrôlé

Distinguez les erreurs de démarrage des erreurs d’opération :

Sandbox de longue durée

Attendez la fin de l’exécution de la commande principale :

Reconnexion

Reconnectez-vous à une sandbox créée lors d’une session ou d’un processus précédent :

Lot parallèle avec une session

Créez de multiples Sandbox et attendez les résultats :
Dernière modification le 15 octobre 2026