5
Penanganan Error dan Interrupt
GhostTR.py tidak punya satu handler global yang seragam. Pembacaan pilihan menu dijaga oleh main, sedangkan pemanggilan opsi dijaga oleh execute_option, dan keduanya memulihkan keadaan dengan memanggil dirinya sendiri secara rekursif, bukan dengan loop. Struktur menu dan dispatch opsi yang dilindungi kedua fungsi ini dibahas di Loop Menu dan Dispatch Opsi.
Peta keadaan saat error dan interrupt
stateDiagram-v2
[*] --> Menu
Menu --> ReadOption: "input Select Option"
ReadOption --> Menu: "ValueError: Please input number"
ReadOption --> RunOption: "int(opt) berhasil"
RunOption --> Menu: "Press enter to continue"
RunOption --> UnknownOption: "ValueError: Option not found"
UnknownOption --> RunOption: "execute_option(opt) rekursif"
RunOption --> Exit: KeyboardInterrupt
ReadOption --> Exit: "KeyboardInterrupt di __main__"
Exit --> [*]
style Menu fill:#2d7d46,color:#fff
style ReadOption fill:#8b5cf6,color:#fff
style RunOption fill:#336791,color:#fff
style UnknownOption fill:#f59e0b,color:#000
style Exit fill:#dc2626,color:#fff
%% fig: Transisi menu GhostTrack saat masukan salah dan interrupt
%% desc: Masukan bukan angka mengembalikan alur ke menu, opsi tak dikenal memutar ulang opsi yang sama, dan Ctrl+C mengakhiri proses.Diagram di atas hanya memuat keadaan yang benar-benar dibentuk oleh kode: Menu adalah pemanggilan option() di dalam main, ReadOption adalah baris int(input(...)), dan Exit adalah exit() yang dipanggil dari dua handler KeyboardInterrupt (GhostTR.py:296-3061).
Masukan bukan angka di main
main membungkus dua pernyataan sekaligus dalam satu blok try: pembacaan opt = int(input(...)) dan pemanggilan execute_option(opt) (GhostTR.py:300-3022). Blok except ValueError mencetak [ ! ] Please input number, menunggu 2 detik, lalu memanggil main() lagi (GhostTR.py:303-3063). Karena main mengawali dirinya dengan clear() dan option(), menu dan banner dicetak ulang dari awal, dan nilai opt yang gagal dibuang.
Pesan itu tidak memeriksa isi exception: variabel e tidak diikat pada blok ini (GhostTR.py:303-3063). Akibatnya Please input number juga muncul untuk ValueError lain yang lolos dari execute_option, walaupun pengguna sebenarnya sudah mengetik angka.
Opsi tidak dikenal dan ValueError
call_option memvalidasi nomor opsi lebih dulu lewat is_in_options, yang membandingkan opt dengan setiap option['num'] dan mengembalikan False bila tidak ada yang cocok (GhostTR.py:252-2564). Bila validasi gagal, call_option melempar raise ValueError('Option not found') (GhostTR.py:219-2215). Setelah lolos validasi, fungsi ini mencari opsi yang cocok lalu memanggil option['func'](); cabang else mencetak No function detected bila kunci func tidak ada (GhostTR.py:222-2276). Seluruh entri pada daftar options memiliki func, termasuk opsi 0 yang memakai exit (GhostTR.py:202-2067), sehingga cabang tersebut tidak pernah aktif pada commit ini.
execute_option menangkap ValueError dari seluruh isi call_option maupun dari prompt Press enter to continue (GhostTR.py:230-2428). Handler-nya mencetak pesan exception dengan print(e), menunggu 2 detik, lalu memanggil execute_option(opt) dengan nomor opsi yang sama (GhostTR.py:235-2389).
⚠️ Pemulihan opsi salah bersifat rekursif tanpa syarat berhenti. Karena
opttidak pernah berubah dancall_optiongagal sebelum barisinput('Press enter to continue'), pesanOption not foundtercetak berulang setiap 2 detik tanpa pernah menampilkan menu lagi. Satu-satunya jalan keluar adalahKeyboardInterrupt(GhostTR.py:230-2428).
KeyboardInterrupt
Ada dua handler KeyboardInterrupt dengan isi yang sama. Yang pertama berada di execute_option dan menangkap Ctrl+C selama sebuah opsi berjalan; handler ini mencetak [ ! ] Exit, menunggu 2 detik, lalu memanggil exit() (GhostTR.py:239-24210). Yang kedua berada di blok if __name__ == '__main__' dan menangkap Ctrl+C yang lolos dari main() (GhostTR.py:309-31511).
Ctrl+C pada prompt Select Option tidak ditangkap main, karena blok except di sana hanya ValueError (GhostTR.py:303-3063). Interrupt tersebut merambat ke handler di __main__ dan menghasilkan keluaran yang sama, sehingga keduanya tidak bisa dibedakan dari layar.
Error di dalam fungsi pelacakan
Sebagian fungsi fitur tidak memiliki try sendiri. IP_Track, misalnya, memanggil int(ip_data['latitude']) dan int(ip_data['longitude']) (GhostTR.py:59-6012); bila nilai dari API tidak bisa dikonversi, ValueError merambat keluar dari call_option dan ditangkap execute_option, lalu opsi yang sama dijalankan ulang sehingga Enter IP target ditanyakan lagi (GhostTR.py:235-2389).
TrackLu adalah satu-satunya fungsi fitur yang menangkap exception sendiri: seluruh badannya berada dalam try, dan except Exception as e mencetak Error : {e} lalu return (GhostTR.py:159-16113). Karena call_option selesai normal setelah return itu, execute_option tetap menampilkan Press enter to continue dan pengguna kembali ke menu tanpa ringkasan hasil. Exception lain di luar ValueError, KeyboardInterrupt, dan blok Exception pada TrackLu tidak memiliki handler di berkas ini.
Ringkasan handler
| Handler | Cakupan | Aksi | Rujukan |
|---|---|---|---|
except ValueError di main | int(input(...)) dan execute_option(opt) | cetak Please input number, time.sleep(2), main() | GhostTR.py:303-3063 |
except ValueError di execute_option | seluruh call_option(opt) dan prompt Press enter to continue | print(e), time.sleep(2), execute_option(opt) | GhostTR.py:235-2389 |
except KeyboardInterrupt di execute_option | seluruh call_option(opt) | cetak Exit, time.sleep(2), exit() | GhostTR.py:239-24210 |
except Exception di TrackLu | badan TrackLu | cetak Error : {e}, return | GhostTR.py:159-16113 |
except KeyboardInterrupt di __main__ | main() | cetak Exit, time.sleep(2), exit() | GhostTR.py:309-31511 |
Perilaku normal menu tanpa error, termasuk isi daftar options, dijelaskan di Loop Menu dan Dispatch Opsi. Batasan penggunaan tool ini setelah kegagalan ditangani dibahas di Batasan dan Etika Penggunaan.