Spaces:
Sleeping
Sleeping
File size: 9,890 Bytes
179eccc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | > [!NOTE]
> Questa documentazione potrebbe contenere contenuti generati dall'IA. Sebbene ci impegniamo per l'accuratezza, potrebbero esserci delle imprecisioni. Si prega di segnalare eventuali problemi tramite:
>
> - [GitHub Issues](https://github.com/PDFMathTranslate-next/PDFMathTranslate-next/issues)
> - Contributo della comunità (PR sono benvenuti!)
## Python API: do_translate_async_stream
### Panoramica
- do_translate_async_stream è il punto di ingresso asincrono di basso livello che traduce un singolo PDF e restituisce un flusso di eventi (progresso/errore/fine).
- È adatto per costruire la propria UI o CLI in cui si desidera un progresso in tempo reale e il controllo completo sui risultati.
- Accetta un SettingsModel validato e un percorso del file e restituisce un generatore asincrono di eventi dict.
### Firma
- Import: `from pdf2zh_next.high_level import do_translate_async_stream`
- Chiamata: `async for event in do_translate_async_stream(settings, file): ...`
- Parametri:
- settings: SettingsModel. Deve essere valido; la funzione chiamerà `settings.validate_settings()`.
- file: str | pathlib.Path. Il singolo PDF da tradurre. Deve esistere.
NOTE
- `settings.basic.input_files` viene ignorato da questa funzione; viene tradotto solo il `file` specificato.
- Se `settings.basic.debug` è True, la traduzione viene eseguita nel processo principale; altrimenti viene eseguita in un sottoprocesso. Lo schema degli eventi è identico in entrambi i casi.
### Contratto del flusso di eventi
Il generatore asincrono produce eventi di tipo dict simili a JSON con i seguenti tipi:
- Evento di riepilogo fase: `stage_summary` (opzionale, può apparire per primo)
- Campi
- `type`: "stage_summary"
- `stages`: lista di oggetti `{ "name": str, "percent": float }` che descrivono la distribuzione stimata del lavoro
- `part_index`: può essere 0 per questo evento di riepilogo
- `total_parts`: numero totale di parti (>= 1)
- Eventi di avanzamento: `progress_start`, `progress_update`, `progress_end`
- Campi comuni
- `type`: uno dei precedenti
- `stage`: nome della fase leggibile dall'uomo (ad es. "Analizza PDF e Crea Rappresentazione Intermedia", "Traduci Paragrafi", "Salva PDF")
- `stage_progress`: float in [0, 100] che indica l'avanzamento all'interno della fase corrente
- `overall_progress`: float in [0, 100] che indica l'avanzamento complessivo
- `part_index`: indice della parte corrente (tipicamente basato su 1 per gli eventi di avanzamento)
- `total_parts`: numero totale di parti (>= 1). Documenti di grandi dimensioni possono essere suddivisi automaticamente.
- `stage_current`: passo corrente all'interno della fase
- `stage_total`: passi totali all'interno della fase
- Evento di completamento: `finish`
- Campi
- `type`: "finish"
- `translate_result`: un **oggetto** che fornisce gli output finali (NOTA: non un dizionario, ma un'istanza di classe)
- `original_pdf_path`: Percorso del PDF di input
- `mono_pdf_path`: Percorso del PDF tradotto monolingue (o None)
- `dual_pdf_path`: Percorso del PDF tradotto bilingue (o None)
- `no_watermark_mono_pdf_path`: Percorso dell'output monolingue senza filigrana (se prodotto), altrimenti None
- `no_watermark_dual_pdf_path`: Percorso dell'output bilingue senza filigrana (se prodotto), altrimenti None
- `auto_extracted_glossary_path`: Percorso del glossario CSV estratto automaticamente (o None)
- `total_seconds`: secondi trascorsi (float)
- `peak_memory_usage`: utilizzo approssimativo della memoria di picco durante la traduzione (float; unità dipendenti dall'implementazione)
- Evento di errore: `error`
- Campi
- `type`: "error"
- `error`: messaggio di errore leggibile dall'uomo
- `error_type`: uno tra `BabeldocError`, `SubprocessError`, `IPCError`, `SubprocessCrashError`, ecc.
- `details`: dettagli opzionali (ad es. errore originale o traceback)
Comportamento importante:
- Un `stage_summary` opzionale può essere emesso prima che il progresso inizi.
- In caso di determinati fallimenti, il generatore emetterà prima un evento `error` e poi solleverà un'eccezione derivata da `TranslationError`. Dovresti sia controllare la presenza di eventi di errore che essere pronto a catturare le eccezioni.
- Gli eventi `progress_update` possono ripetersi con valori identici; i consumatori dovrebbero eseguire il debounce se necessario.
- Interrompi il consumo del flusso quando ricevi un evento `finish`.
### Esempio di utilizzo minimo (Async)
```python
import asyncio
from pathlib import Path
from pdf2zh_next.high_level import do_translate_async_stream
# Assume you already have a valid SettingsModel instance named `settings`
# and a PDF file path
async def translate_one(settings, pdf_path: str | Path):
try:
async for event in do_translate_async_stream(settings, pdf_path):
etype = event.get("type")
if etype == "stage_summary":
# Optional pre-flight summary of stages
stages = event.get("stages", [])
print("Stage summary:", ", ".join(f"{s['name']}:{s['percent']:.2f}" for s in stages))
elif etype in {"progress_start", "progress_update", "progress_end"}:
stage = event.get("stage")
stage_prog = event.get("stage_progress") # 0..100
overall = event.get("overall_progress") # 0..100
part_i = event.get("part_index")
part_n = event.get("total_parts")
print(f"[{etype}] {stage} | stage {stage_prog:.1f}% | overall {overall:.1f}% (part {part_i}/{part_n})")
elif etype == "error":
# You will also get a raised exception after this yield
print("[error]", event.get("error"), event.get("error_type"))
elif etype == "finish":
result = event["translate_result"]
print("Done in", getattr(result, "total_seconds", None), "s")
print("Mono:", getattr(result, "mono_pdf_path", None))
print("Dual:", getattr(result, "dual_pdf_path", None))
print("No-watermark Mono:", getattr(result, "no_watermark_mono_pdf_path", None))
print("No-watermark Dual:", getattr(result, "no_watermark_dual_pdf_path", None))
print("Glossary:", getattr(result, "auto_extracted_glossary_path", None))
print("Peak memory:", getattr(result, "peak_memory_usage", None))
break
except Exception as exc:
# Catch exceptions raised by the stream after an error event
print("Translation failed:", exc)
# asyncio.run(translate_one(settings, "/path/to/file.pdf"))
```
### Annullamento
Puoi annullare l'attività consumando il flusso. L'annullamento viene propagato al processo di traduzione sottostante.
```python
import asyncio
from pdf2zh_next.high_level import do_translate_async_stream
async def cancellable(settings, pdf):
task = asyncio.create_task(_consume(settings, pdf))
await asyncio.sleep(1.0) # let it start
task.cancel()
try:
await task
except asyncio.CancelledError:
print("Cancelled")
async def _consume(settings, pdf):
async for event in do_translate_async_stream(settings, pdf):
if event["type"] == "finish":
break
```
### Forme di Evento di Esempio
Riepilogo dello stage evento (esempio):
```json
{
"type": "stage_summary",
"stages": [
{"name": "Parse PDF and Create Intermediate Representation", "percent": 0.1086},
{"name": "DetectScannedFile", "percent": 0.0188},
{"name": "Parse Page Layout", "percent": 0.1079}
// ... more stages ...
],
"part_index": 0,
"total_parts": 1
}
```
Progress event (esempio):
```json
{
"type": "progress_update",
"stage": "Translate Paragraphs",
"stage_progress": 2.04,
"stage_current": 1,
"stage_total": 49,
"overall_progress": 53.44,
"part_index": 1,
"total_parts": 1
}
```
Finish event (esempio):
```json
{
"type": "finish",
"translate_result": {
"original_pdf_path": "pdf2zh_files/<session>/table.pdf",
"mono_pdf_path": "pdf2zh_files/<session>/table.zh-CN.mono.pdf",
"dual_pdf_path": "pdf2zh_files/<session>/table.zh-CN.dual.pdf",
"no_watermark_mono_pdf_path": "pdf2zh_files/<session>/table.no_watermark.zh-CN.mono.pdf",
"no_watermark_dual_pdf_path": "pdf2zh_files/<session>/table.no_watermark.zh-CN.dual.pdf",
"auto_extracted_glossary_path": "pdf2zh_files/<session>/table.zh-CN.glossary.csv",
"total_seconds": 42.83,
"peak_memory_usage": 4651.55
}
}
```
Evento di errore (esempio):
```json
{
"type": "error",
"error": "Babeldoc translation error: <message>",
"error_type": "BabeldocError",
"details": "<optional original error or traceback>"
}
```
### Note e migliori pratiche
- Gestire sempre sia gli eventi di errore che le eccezioni dal generatore.
- Interrompere il ciclo su `finish` per evitare lavoro non necessario.
- Assicurarsi che il `file` esista e che `settings.validate_settings()` passi prima della chiamata.
- I documenti di grandi dimensioni potrebbero essere divisi; utilizzare `part_index/total_parts` e `overall_progress` per guidare la tua UI.
- Debounce `progress_update` se la tua UI è sensibile a ripetuti aggiornamenti identici.
- `report_interval` (SettingsModel): controlla solo la frequenza di emissione degli eventi `progress_update`. Non influisce su `stage_summary`, `progress_start`, `progress_end` o `finish`. Il valore predefinito è 0.1s e il minimo consentito è 0.05s. Come da logica del monitor di avanzamento, quando `stage_total <= 3`, gli aggiornamenti non sono limitati da `report_interval`.
<div align="right">
<h6><small>Parte del contenuto di questa pagina è stata tradotta da GPT e potrebbe contenere errori.</small></h6> |