Přeskočit na hlavní obsah
Tento projekt je v betě. Našel jsi chybu? Otevřít issue na GitHubu. Máš otázku nebo nápad? Zeptej se v Discussions — rádi si poslechneme tvou zpětnou vazbu!
Jaká je kvalita překladu na této stránce?

Zápis logů a zpracování chyb

Nastav kód workflow tak, aby zapisoval logy, hlásil chyby do tvého lokálního notebooku a při zrušení jobu ukládal částečnou práci. Jak tyto výstupy přečíst z lokálního notebooku, najdeš v části Spuštění spravovaného workflow.

Ve workflowV tvém lokálním notebooku
Zapisuj pomocí loggeru z modulu logging nebo zavolej print().job.logs() vrátí řádky.
Vyvolej výjimku nebo skonči s nenulovým kódem.job.status() vrátí ERROR a job.logs() zobrazí traceback.
Zavolej send_error().job.error_message() a job.events(type="ERROR") vrátí kód, zprávu a podrobnosti.
Zavolej save_result() v handleru SIGTERM.job.result() vrátí částečný výsledek zrušeného jobu.

Zápis logů​

Cokoli, co workflow zapíše na standardní výstup nebo standardní chybový výstup, jde do logů jobu. Logy přečteš pomocí job.logs() během běhu jobu nebo po jeho skončení.

Nastavení loggeru​

Použij modul logging ze standardní knihovny Pythonu. logging.basicConfig() zapisuje na standardní chybový výstup, který se do logů dostane bez zpoždění. Formát v následujícím příkladu přidává ke každému řádku časové razítko:

source_files/my_workflow.py

import logging

logging.basicConfig(
level=logging.WARNING,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
logger = logging.getLogger("my_workflow")
logger.setLevel(logging.INFO)

logger.info("Transpiled %d circuits: depth %d -> %d", len(circuits), 1250, 730)
2026-11-01 21:57:35,195 INFO my_workflow: Transpiled 12 circuits: depth 1250 -> 730

level=logging.WARNING skryje zprávy INFO z jiných balíčků a logger.setLevel(logging.INFO) ponechá zprávy INFO pro tvůj vlastní logger. qiskit_ibm_runtime nastavuje svou vlastní úroveň pomocí proměnné prostředí QISKIT_IBM_RUNTIME_LOG_LEVEL.

print() se do logů také dostane, ale standardní výstup je ukládán do vyrovnávací paměti, takže vypsané řádky se nemusí zobrazit až do skončení jobu. Pokud používáš print(), předej flush=True.

Nastavení úrovně logování pro každý běh​

Chceš-li ladit jeden běh bez změny kódu, předej úroveň logování jako argument:

run_workflow_remotely.ipynb

job = my_workflow.run(circuits=circuits, log_level="DEBUG")

Aby to fungovalo, nastav úroveň svého loggeru z argumentu:

source_files/my_workflow.py

from qiskit_serverless import get_arguments

arguments = get_arguments()
logger.setLevel(arguments.get("log_level", "INFO"))

Pokud workflow má schéma argumentů, deklaruj v něm log_level, například jako {"enum": ["DEBUG", "INFO", "WARNING"]}.

Osvědčený postup: rozhodni, co logovat​

Loguj tolik, abys mohl běh z logů zrekonstruovat:

  • Na začátku zaloguj, co běh obdržel. Zaloguj název backendu, počet obvodů a další nastavení, která se mezi běhy mění.

  • Loguj začátek a konec každé fáze. Používej pevné zprávy, které můžeš vyhledávat.

  • Loguj iterace v pevném intervalu. Například loguj řádek jako iteration 10/200, energy=-1.1000 každých 10 iterací, nikoli každou iteraci.

  • Loguj výjimky pomocí logger.exception() uvnitř bloku except. Řádek obsahuje úplný traceback, i když se workflow z chyby zotaví.

  • Vypni indikátory průběhu. Logy ukládají každé překreslení indikátoru průběhu, například z tqdm, jako samostatný řádek. Předej tqdm argument disable=True nebo loguj v intervalech.

  • Udržuj logy malé. Neloguj velká data, například každý shot. Spravovaný workflow uchovává pro každý job jen nejnovějších 50 MB logů.

  • Slova „error“ a „exception“ používej jen ve zprávách o selháních. Pokud neúspěšný job nenahlásil svou chybu, výjimka, kterou job.result() vyvolá, obsahuje jen řádky logu, které tato slova obsahují.

Osvědčený postup: hlas chyby pomocí send_error()​

Když workflow vyvolá výjimku, job skončí se stavem ERROR a traceback jde do logů. Spravovaný workflow chybu neukládá, ani u ServerlessError. job.error_message() vrací {} a výjimka, kterou job.result() vyvolá, obsahuje jen řádky logu, které obsahují error nebo exception. Kontroly typů a rozsahů argumentů patří do schématu argumentů, které chybný běh odmítne ještě před spuštěním jobu.

Hlas každou chybu, která zastaví workflow, pomocí send_error(), aby tvůj lokální notebook dostal stručnou chybu s kódem a podrobnostmi:

run_workflow_remotely.ipynb

print(job.error_message())

| Message: The circuit has more qubits than the backend.
| Code: 4500
| Exception: InputError
| Details:
| - circuit_qubits: 10
| - backend_qubits: 5

job.result() vyvolá QiskitServerlessException se stejným textem.

Abys to povolil, vyvolej ServerlessError v místě, kde chyba nastane, a kód svého entrypointu obal blokem try, který odešle každou chybu pomocí send_error(). Workflow přidá tento handler do Catalog Functions, ale ne do spravovaných workflow:

source_files/my_workflow.py

from qiskit_serverless import ServerlessError, send_error

class InputError(ServerlessError):
"""The arguments are valid, but the workflow cannot use them."""

def main():
...
if num_qubits > backend.num_qubits:
raise InputError(
code="4500",
message="The circuit has more qubits than the backend.",
details={"circuit_qubits": num_qubits, "backend_qubits": backend.num_qubits},
)
...

try:
main()
except Exception as error:
send_error(
code=getattr(error, "code", "1"),
message=getattr(error, "message", repr(error)),
exception=type(error).__name__,
args=getattr(error, "details", None),
)
raise
  • Vyvolej chybu znovu. Závěrečný raise zachová traceback v protokolech a ukončí úlohu se stavem ERROR.

  • Vytvoř podtřídu ServerlessError pro pojmenování skupiny chyb. Handler odešle název třídy, například InputError, jako pole exception.

  • Handler zachytí i další výjimky. Dostanou kód 1 a jejich repr() se stane zprávou, například ValueError('bad shots').

Nahlášení problému a pokračování​

send_error() workflow nezastaví ani nezmění jeho stav, takže můžeš hlásit i problémy, ze kterých se workflow zotaví, například každý obvod, který přeskočí:

source_files/my_workflow.py

valid_circuits = []
for index, circuit in enumerate(circuits):
if circuit.num_qubits > backend.num_qubits:
send_error(
code="4501",
message="Skipped a circuit that is wider than the backend.",
exception="InputError",
args={"circuit_index": index},
)
continue
valid_circuits.append(circuit)

job.events(type="ERROR") vrací všechny chyby, které workflow nahlásilo, včetně chyb úlohy, která skončila se stavem DONE. Viz Zjištění příčiny chyby.

  • Předávej čísla a řetězce v args. error_message() zobrazí pouze první položku seznamu.

  • Zkontroluj návratovou hodnotu. Pokud workflow nemůže chybu uložit, například protože kód běží mimo úlohu, send_error() zapíše chybu do protokolů a vrátí False.

Úklid při zrušení úlohy​

Když zrušíš úlohu, workflow pošle tvému entrypointu SIGTERM, nahraje závěrečné protokoly a vypne prostředí. Bez handleru se Python okamžitě zastaví a bloky finally se nespustí. Workflow se také pokusí zrušit úlohy a sessions na QPU, které workflow spustilo pomocí get_runtime_service(). Viz Zrušení propojených úloh na QPU.

Chceš-li zachovat částečnou práci, zaregistruj handler pro SIGTERM. Tvůj lokální notebook pak získá částečný výsledek ze zrušené úlohy:

run_workflow_remotely.ipynb

job.cancel()
print(job.result()) # {'status': 'canceled', 'partial_results': [...]}

Abys to povolil, přidej handler na začátek svého entrypointu:

source_files/my_workflow.py

import signal
import sys

from qiskit_serverless import save_result

partial_results = []

def handle_sigterm(signum, frame):
save_result({"status": "canceled", "partial_results": partial_results})
sys.exit(0)

signal.signal(signal.SIGTERM, handle_sigterm)

sys.exit() v handleru vyvolá SystemExit v kódu, který právě běží, takže se bloky finally spustí dříve, než skript skončí. Úloha stále skončí se stavem CANCELED.

Udržuj handler krátký, protože workflow vypne prostředí brzy po SIGTERM. U dlouhých běhů také ukládej kontrolní body, aby mohl pozdější běh pokračovat poté, co úloha selže nebo dosáhne 24hodinového limitu. Viz Doporučený postup: kontrolní body u dlouhých úloh.

Další kroky​

Doporučení