Langkau ke kandungan utama
Projek ini dalam fasa beta. Jumpa pepijat? Buat isu GitHub. Ada soalan atau idea? Tanya dalam Discussions — kami suka dengar maklum balas anda!
Bagaimana kualiti terjemahan pada halaman ini?

Tulis log dan kendalikan ralat

Sediakan kod aliran kerja anda untuk menulis log, melaporkan ralat ke notebook tempatan anda, dan menyimpan kerja separa apabila job dibatalkan. Untuk membaca output ini daripada notebook tempatan anda, lihat Jalankan aliran kerja terurus.

Dalam aliran kerjaDalam notebook tempatan anda
Tulis dengan logger daripada modul logging, atau panggil print().job.logs() mengembalikan baris tersebut.
Timbulkan pengecualian, atau keluar dengan kod bukan sifar.job.status() mengembalikan ERROR, dan job.logs() menunjukkan traceback.
Panggil send_error().job.error_message() dan job.events(type="ERROR") mengembalikan kod, mesej dan butiran.
Panggil save_result() dalam pengendali SIGTERM.job.result() mengembalikan hasil separa bagi job yang dibatalkan.

Tulis log​

Apa-apa sahaja yang ditulis oleh aliran kerja ke output standard atau ralat standard masuk ke log job. Baca log dengan job.logs() semasa job berjalan atau selepas ia tamat.

Sediakan logger​

Gunakan modul logging daripada pustaka standard Python. logging.basicConfig() menulis ke ralat standard, yang sampai ke log tanpa kelewatan. Format dalam contoh berikut menambah cap masa pada setiap baris:

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 menyembunyikan mesej INFO daripada pakej lain, dan logger.setLevel(logging.INFO) mengekalkan mesej INFO untuk logger anda sendiri. qiskit_ibm_runtime menetapkan tahapnya sendiri dengan pemboleh ubah persekitaran QISKIT_IBM_RUNTIME_LOG_LEVEL.

print() juga sampai ke log, tetapi output standard dibuffer, jadi baris yang dicetak mungkin tidak muncul sehingga job tamat. Jika anda menggunakan print(), hantar flush=True.

Tetapkan tahap log untuk setiap larian​

Untuk menyahpepijat satu larian tanpa mengubah kod, hantar tahap log sebagai argumen:

run_workflow_remotely.ipynb

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

Untuk membolehkan ini, tetapkan tahap logger anda daripada argumen:

source_files/my_workflow.py

from qiskit_serverless import get_arguments

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

Jika aliran kerja mempunyai skema argumen, isytiharkan log_level di dalamnya, contohnya sebagai {"enum": ["DEBUG", "INFO", "WARNING"]}.

Amalan terbaik: tentukan apa yang perlu dilog​

Log secukupnya untuk membina semula larian daripada lognya:

  • Pada permulaan, log apa yang diterima larian. Log nama backend, bilangan litar, dan tetapan lain yang berubah antara larian.

  • Log permulaan dan penghujung setiap peringkat. Gunakan mesej tetap yang boleh anda cari.

  • Log lelaran pada sela tetap. Contohnya, log baris seperti iteration 10/200, energy=-1.1000 setiap 10 lelaran, bukannya setiap lelaran.

  • Log pengecualian dengan logger.exception() di dalam blok except. Baris itu merangkumi traceback penuh, walaupun aliran kerja pulih daripada ralat.

  • Matikan bar kemajuan. Log menyimpan setiap muat semula bar kemajuan, seperti daripada tqdm, sebagai baris berasingan. Hantar disable=True kepada tqdm, atau log pada sela masa sebaliknya.

  • Pastikan log kecil. Jangan log data besar, seperti setiap shot. Aliran kerja terurus hanya menyimpan 50 MB log terbaharu bagi setiap job.

  • Gunakan perkataan "error" dan "exception" hanya dalam mesej tentang kegagalan. Jika job yang gagal tidak melaporkan ralatnya, pengecualian yang ditimbulkan oleh job.result() hanya mengandungi baris log yang memasukkan perkataan ini.

Amalan terbaik: laporkan ralat dengan send_error()​

Apabila aliran kerja menimbulkan pengecualian, job berakhir dengan status ERROR, dan traceback masuk ke log. Aliran kerja terurus tidak menyimpan ralat itu, walaupun untuk ServerlessError. job.error_message() mengembalikan {}, dan pengecualian yang ditimbulkan oleh job.result() hanya mengandungi baris log yang memasukkan error atau exception. Semakan jenis dan julat argumen sepatutnya berada dalam skema argumen, yang menolak larian yang buruk sebelum job bermula.

Laporkan setiap ralat yang menghentikan aliran kerja dengan send_error(), supaya notebook tempatan anda mendapat ralat ringkas dengan kod dan butiran:

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() menimbulkan QiskitServerlessException dengan teks yang sama.

Untuk membolehkan ini, timbulkan ServerlessError di tempat ralat berlaku, dan bungkus kod titik masuk anda dalam blok try yang menghantar sebarang ralat dengan send_error(). Aliran kerja menambah pengendali ini kepada Catalog Functions, tetapi tidak kepada aliran kerja terurus:

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
  • Timbulkan ralat itu sekali lagi. raise terakhir mengekalkan traceback dalam log dan menamatkan job dengan status ERROR.

  • Jadikan ServerlessError subkelas untuk menamakan satu kumpulan ralat. Pengendali menghantar nama kelas, seperti InputError, sebagai medan exception.

  • Pengecualian lain juga sampai ke pengendali. Ia mendapat kod 1, dan repr() mereka menjadi mesej, seperti ValueError('bad shots').

Laporkan masalah dan teruskan​

send_error() tidak menghentikan aliran kerja atau mengubah statusnya, jadi anda juga boleh melaporkan masalah yang dipulihkan oleh aliran kerja, seperti setiap litar yang dilangkaunya:

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") mengembalikan setiap ralat yang dilaporkan oleh aliran kerja, termasuk ralat bagi job yang berakhir dengan status DONE. Lihat Cari punca ralat.

  • Hantar nombor dan rentetan dalam args. error_message() hanya menunjukkan item pertama dalam senarai.

  • Semak nilai pulangan. Jika aliran kerja tidak dapat menyimpan ralat, contohnya kerana kod berjalan di luar job, send_error() menulis ralat ke log dan mengembalikan False.

Bersihkan apabila job dibatalkan​

Apabila anda membatalkan job, aliran kerja menghantar SIGTERM kepada titik masuk anda, memuat naik log akhir, dan menutup persekitaran. Tanpa pengendali, Python berhenti serta-merta, dan blok finally tidak dijalankan. Aliran kerja juga cuba membatalkan job dan session QPU yang dimulakan oleh aliran kerja dengan get_runtime_service(). Lihat Batalkan job QPU yang dipautkan.

Untuk menyimpan kerja separa, daftarkan pengendali untuk SIGTERM. Notebook tempatan anda kemudian mendapat hasil separa daripada job yang dibatalkan:

run_workflow_remotely.ipynb

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

Untuk membolehkan ini, tambahkan pengendali pada permulaan titik masuk anda:

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() dalam pengendali menimbulkan SystemExit dalam kod yang sedang berjalan, jadi blok finally dijalankan sebelum skrip tamat. Job masih berakhir dengan status CANCELED.

Pastikan pengendali ringkas, kerana aliran kerja menutup persekitaran sejurus selepas SIGTERM. Untuk larian yang panjang, simpan juga titik semak, supaya larian kemudian boleh disambung semula selepas kerja gagal atau mencapai had 24 jam. Lihat Amalan terbaik: titik semak untuk kerja panjang.

Langkah seterusnya​

Cadangan