Saya selalu menggunakan file JSON untuk konfigurasi aplikasi saya. Saya mulai menggunakan mereka sejak saya mengkodekan banyak Java, dan sekarang saya bekerja terutama pada sisi server dan pengembangan data ilmu Python dan saya tidak yakin apakah JSON adalah cara yang tepat untuk melangkah lebih jauh.
Saya telah melihat Seledri menggunakan file Python aktual untuk konfigurasi. Awalnya saya skeptis tentang hal itu. Tetapi gagasan untuk menggunakan struktur data Python sederhana untuk konfigurasi mulai tumbuh pada saya. Beberapa pro:
- Struktur data akan sama dengan yang biasa saya lakukan. Jadi, saya tidak perlu mengubah kerangka berpikir.
- IDE Saya (PyCharm) memahami koneksi antara konfigurasi dan kode. Ctrl+ Bmemungkinkan untuk beralih antara konfigurasi dan kode dengan mudah.
- Saya tidak perlu bekerja dengan IMO JSON ketat yang tidak perlu . Saya melihat Anda tanda kutip ganda, tidak ada koma tertinggal dan tidak ada komentar.
- Saya dapat menulis konfigurasi pengujian di aplikasi yang sedang saya kerjakan, kemudian dengan mudah mem-portingnya ke file konfigurasi tanpa harus melakukan konversi dan penguraian JSON.
- Dimungkinkan untuk melakukan skrip yang sangat sederhana dalam file konfigurasi jika benar-benar diperlukan. (Meskipun ini harus sangat, sangat terbatas.)
Jadi, pertanyaan saya adalah: Jika saya beralih, bagaimana saya menembak diri saya sendiri?
Tidak ada pengguna akhir yang tidak terampil akan menggunakan file konfigurasi. Setiap perubahan pada file konfigurasi saat ini berkomitmen untuk Git dan diluncurkan ke server kami sebagai bagian dari penyebaran berkelanjutan. Tidak ada perubahan konfigurasi manual, kecuali ada keadaan darurat atau sedang dalam pengembangan.
(Saya sudah mempertimbangkan YAML , tetapi sesuatu tentang hal itu membuat saya kesal. Jadi, untuk saat ini di luar meja Amerika.)
sumber
Jawaban:
Menggunakan bahasa skrip sebagai ganti file konfigurasi tampak hebat pada pandangan pertama: Anda memiliki kekuatan penuh dari bahasa itu tersedia dan dapat dengan mudah
eval()
atau hanyaimport
itu. Dalam praktiknya, ada beberapa gotcha:itu adalah bahasa pemrograman, yang perlu dipelajari. Untuk mengedit konfigurasi, Anda perlu mengetahui bahasa ini dengan cukup baik. File konfigurasi biasanya memiliki format yang lebih sederhana sehingga lebih sulit untuk dibuat salah.
ini adalah bahasa pemrograman, yang berarti bahwa konfigurasi bisa menjadi sulit untuk di-debug. Dengan file konfigurasi normal Anda melihatnya dan melihat nilai apa yang disediakan untuk setiap properti. Dengan skrip, Anda berpotensi perlu menjalankannya terlebih dahulu untuk melihat nilainya.
itu adalah bahasa pemrograman, yang membuatnya sulit untuk mempertahankan pemisahan yang jelas antara konfigurasi dan program yang sebenarnya. Terkadang Anda memang menginginkan ekstensibilitas semacam ini, tetapi pada saat itu Anda mungkin mencari sistem plugin yang sebenarnya.
itu adalah bahasa pemrograman, yang berarti bahwa konfigurasi dapat melakukan apa saja yang dapat dilakukan oleh bahasa pemrograman. Jadi baik Anda menggunakan solusi kotak pasir yang meniadakan banyak fleksibilitas bahasa, atau Anda menaruh kepercayaan tinggi pada penulis konfigurasi.
Jadi menggunakan skrip untuk konfigurasi mungkin OK jika audiens alat Anda adalah pengembang, mis. Sphinx config atau the setup.py dalam proyek Python. Program lain dengan konfigurasi yang dapat dieksekusi adalah shell seperti Bash, dan editor seperti Vim.
Diperlukan penggunaan bahasa pemrograman untuk konfigurasi jika konfigurasi tersebut mengandung banyak bagian kondisional, atau jika itu menyediakan panggilan balik / plugin. Menggunakan skrip secara langsung alih-alih eval () - beberapa bidang konfigurasi cenderung lebih dapat disangkal (pikirkan tentang tumpukan jejak dan nomor baris!).
Langsung menggunakan bahasa pemrograman juga merupakan ide yang baik jika konfigurasi Anda sangat berulang sehingga Anda menulis skrip untuk membuat autogenerate konfigurasi secara otomatis. Tetapi mungkin model data yang lebih baik untuk konfigurasi dapat menghapus kebutuhan untuk konfigurasi eksplisit seperti itu? Misalnya, mungkin bermanfaat jika file config dapat berisi placeholder yang nanti Anda perluas. Fitur lain yang kadang-kadang terlihat adalah beberapa file konfigurasi dengan prioritas berbeda yang dapat saling menimpa, meskipun itu menimbulkan beberapa masalah tersendiri.
Dalam sebagian besar kasus, file INI, file properti Java, atau dokumen YAML jauh lebih cocok untuk konfigurasi. Untuk model data yang kompleks, XML juga dapat diterapkan. Seperti yang telah Anda catat, JSON memiliki beberapa aspek yang membuatnya tidak cocok sebagai file konfigurasi yang dapat diedit oleh manusia, meskipun ini adalah format pertukaran data yang bagus.
sumber
sendmail.cf
. Itu akan menunjukkan bahwa menggunakan bahasa skrip aktual mungkin bermanfaat, karena yang sebenarnya dirancang untuk Turing-lengkap. Namun , Turing-kelengkapan dan "Tetris-kelengkapan" adalah dua hal yang berbeda, dan sementarasendmail.cf
dapat menghitung fungsi sewenang-wenang, itu tidak dapat mengirim Anda/etc/passwd
melalui net atau memformat harddisk Anda, yang Python atau Perl akan mampu.Memberi +1 ke semua jawaban amon . Saya ingin menambahkan ini:
Anda akan menyesal menggunakan kode Python sebagai bahasa konfigurasi Anda saat pertama kali Anda ingin mengimpor konfigurasi yang sama dari dalam kode yang ditulis dalam bahasa yang berbeda. Misalnya jika kode itu adalah bagian dari proyek Anda dan itu ditulis dalam C ++ atau Ruby atau sesuatu yang lain perlu melakukan konfigurasi, Anda harus menautkan juru bahasa Python sebagai pustaka atau parsing konfigurasi dalam proses Python, keduanya yang canggung, sulit, atau mahal.
Semua kode yang mengimpor konfigurasi ini hari ini dapat ditulis dalam Python, dan Anda mungkin berpikir ini akan benar besok juga, tetapi apakah Anda tahu pasti?
Anda bilang Anda akan menggunakan logika (apa pun yang struktur data statis) dalam konfigurasi Anda hemat jika sama sekali, yang bagus, tetapi jika ada sedikit dari itu sama sekali, Anda akan merasa sulit di masa depan untuk membatalkannya sehingga Anda dapat kembali ke file konfigurasi deklaratif.
EDIT untuk catatan: beberapa orang telah mengomentari jawaban ini tentang seberapa besar atau tidak mungkin suatu proyek akan berhasil sepenuhnya ditulis ulang dalam bahasa lain. Adalah adil untuk mengatakan bahwa penulisan ulang yang kompatibel dengan mundur lengkap mungkin jarang terlihat. Apa yang sebenarnya ada dalam pikiran saya adalah bagian-bagian dari proyek yang sama (dan membutuhkan akses ke konfigurasi yang sama) yang ditulis dalam berbagai bahasa. Misalnya, melayani tumpukan dalam C ++ untuk kecepatan, pembersihan basis data batch di Python, beberapa skrip shell sebagai lem. Jadi habiskan pemikiran untuk kasus itu juga :)
sumber
key=value
tugas konfigurasi, saya tidak melihat mengapa program Java / C ++ tidak bisa membaca file Python sebagai file teks biasa dan menguraikannya sama jika mereka perlu pindah ke sesuatu yang lain di masa depan. Saya tidak melihat perlunya juru bahasa Python yang lengkap.Jawaban lain sudah sangat bagus, saya hanya akan membawa pengalaman penggunaan dunia nyata dalam beberapa proyek.
Pro
Mereka sebagian besar sudah dijabarkan:
eval
); ini bekerja secara otomatis bahkan untuk tipe data yang lebih kompleks (dalam program kami, kami memiliki titik-titik geometris dan transformasi, yang dibuang / dimuat dengan baik melaluirepr
/eval
);Cons
repr
. Ini jelas hal yang buruk.Bahkan jika Anda menggunakan Python, memodifikasi file konfigurasi dari kode adalah masalah nyata, karena ... yah, memodifikasi kode bukanlah hal yang sepele, terutama kode yang memiliki sintaks yang kaya dan tidak dalam LISP atau serupa. Salah satu program kita memiliki file konfigurasi yang Python, awalnya ditulis dengan tangan, tetapi yang kemudian ternyata itu akan berguna untuk memanipulasi melalui perangkat lunak (pengaturan tertentu adalah daftar hal-hal yang cara sederhana untuk menyusun ulang menggunakan GUI). Ini adalah masalah besar, karena:
Bandingkan ini dengan JSON, INI atau (God forbid!) XML, di mana representasi dalam memori selalu dapat diedit dan ditulis kembali baik tanpa kehilangan data (XML, di mana sebagian besar parser DOM dapat menyimpan spasi putih dalam simpul teks dan simpul komentar) atau setidaknya kehilangan hanya beberapa pemformatan (JSON, di mana format itu sendiri tidak memungkinkan lebih dari data mentah yang Anda baca).
Jadi, seperti biasa, tidak ada solusi yang jelas; kebijakan saya saat ini tentang masalah ini adalah:
jika file konfigurasi adalah:
file Python mungkin merupakan ide yang valid;
jika sebaliknya:
format "hanya data" mungkin merupakan ide yang lebih baik.
Perhatikan bahwa tidak perlu membuat pilihan tunggal - Saya baru-baru ini menulis aplikasi yang menggunakan kedua pendekatan. Saya memiliki file yang hampir tidak pernah dimodifikasi dengan pengaturan pertama, pengaturan tulisan tangan di mana ada keuntungan memiliki bonus Python yang bagus, dan file JSON untuk konfigurasi yang diedit dari UI.
sumber
note:
bidang yang diabaikan untuk konfigurasi.curl ... | bash
, bahkan lebih mudah. :-PPertanyaan utamanya adalah: apakah Anda ingin file konfigurasi Anda berada dalam beberapa bahasa lengkap Turing (seperti Python)? Jika Anda ingin itu, Anda mungkin juga mempertimbangkan embedding beberapa lainnya (Turing lengkap) bahasa scripting seperti Guile atau Lua (karena ada bisa dianggap sebagai "sederhana" untuk menggunakan, atau untuk menanamkan, dari Python adalah; membaca bab tentang Memperluas & Embedding Python ). Saya tidak akan membahas hal itu lebih lanjut (karena jawaban lain - oleh Amon - bahas secara mendalam) tetapi perhatikan bahwa menanamkan bahasa skrip ke dalam aplikasi Anda adalah pilihan arsitektur utama , yang harus Anda pertimbangkan sejak dini.; Saya benar-benar tidak merekomendasikan membuat pilihan itu nanti!
Contoh terkenal dari program yang dapat dikonfigurasi melalui "skrip" adalah editor emacs GNU (atau mungkin AutoCAD di ranah kepemilikan); jadi ketahuilah bahwa jika Anda menerima skrip, beberapa pengguna akhirnya akan menggunakan - dan mungkin menyalahgunakan, di sudut pandang Anda - fasilitas itu secara luas dan membuat skrip multi-ribu baris; karena itu pilihan bahasa scripting yang cukup baik adalah penting.
Namun (setidaknya pada sistem POSIX), Anda mungkin mempertimbangkan untuk mengaktifkan "file" konfigurasi untuk dihitung secara dinamis pada waktu inisialisasi (tentu saja, meninggalkan beban konfigurasi yang waras kepada admin atau pengguna sistem Anda; sebenarnya itu adalah konfigurasi teks yang berasal dari beberapa file atau dari beberapa perintah). Untuk itu, Anda bisa langsung mengadopsi konvensi (dan mendokumentasikannya ) bahwa path file konfigurasi yang dimulai dengan misalnya a
!
atau a|
sebenarnya adalah perintah shell yang akan Anda baca sebagai pipa . Ini membuat pengguna Anda memiliki pilihan untuk menggunakan "preprocessor" atau "bahasa scripting" apa pun yang paling dikenalnya.(Anda perlu mempercayai pengguna Anda tentang masalah keamanan jika Anda menerima konfigurasi yang dihitung secara dinamis)
Jadi dalam kode inisialisasi Anda, Anda
main
akan (misalnya) menerima beberapa--config
argumenconfarg
dan mendapatkan beberapaFILE*configf;
darinya. Jika argumen itu dimulai dengan!
(yaitu jika(confarg[0]=='!')
....), Anda akan menggunakanconfigf = popen(confarg+1, "r");
dan menutup pipa itu denganpclose(configf);
. Kalau tidak, Anda akan menggunakanconfigf=fopen(confarg, "r");
dan menutup file itu denganfclose(configf);
(jangan lupa memeriksa kesalahan). Lihat pipa (7) , popen (3) , fopen (3) . Untuk aplikasi yang dikodekan dalam Python, baca tentang os.popen , dll ...(mendokumentasikan juga untuk pengguna aneh yang ingin meneruskan file konfigurasi yang dinamai
!foo.config
untuk melewati./!foo.config
untuk memotongpopen
trik di atas)BTW, trik semacam itu hanya kenyamanan (untuk menghindari mengharuskan pengguna tingkat lanjut untuk misalnya kode beberapa skrip shell untuk menghasilkan file konfigurasi ). Jika pengguna ingin melaporkan bug apa pun, ia harus mengirimi Anda file konfigurasi yang dihasilkan ...
Perhatikan bahwa Anda juga dapat merancang aplikasi Anda dengan kemampuan untuk menggunakan dan memuat plugin pada saat inisialisasi, misalnya dengan dlopen (3) (dan Anda perlu mempercayai pengguna Anda tentang plugin itu). Sekali lagi, ini adalah keputusan arsitektur yang sangat penting (dan Anda perlu mendefinisikan dan menyediakan beberapa API dan konvensi yang agak stabil tentang plugin ini dan aplikasi Anda).
Untuk aplikasi yang dikodekan dalam bahasa scripting seperti Python, Anda juga dapat menerima beberapa argumen program untuk eval atau exec atau primitif serupa. Sekali lagi, masalah keamanan menjadi perhatian pengguna (lanjut) .
Mengenai format teks untuk file konfigurasi Anda (baik itu dihasilkan atau tidak), saya percaya bahwa Anda sebagian besar perlu mendokumentasikannya dengan baik (dan pilihan beberapa format tertentu tidak begitu penting; namun saya sarankan agar pengguna Anda dapat menempatkan beberapa komentar-dilewati- di dalamnya). Anda dapat menggunakan JSON (lebih disukai dengan beberapa parser JSON yang menerima dan melewatkan komentar dengan biasa
//
sampai eol atau/*
...*/
...), atau YAML, atau XML, atau INI atau hal Anda sendiri. Parsing file konfigurasi cukup mudah (dan Anda akan menemukan banyak perpustakaan yang terkait dengan tugas itu).sumber
Menambah jawaban Amon, sudahkah Anda mempertimbangkan alternatif? JSON mungkin lebih dari yang Anda butuhkan, tetapi file Python mungkin akan memberi Anda masalah di masa depan karena alasan yang disebutkan di atas.
Namun Python sudah memiliki parser konfigurasi untuk bahasa konfigurasi yang sangat sederhana yang dapat memenuhi semua kebutuhan Anda. The
ConfigParser
modul menerapkan bahasa config sederhana.sumber
Saya sudah lama bekerja dengan beberapa perangkat lunak terkenal yang file konfigurasinya ditulis dalam TCL, jadi idenya bukanlah hal baru. Ini bekerja cukup baik, karena pengguna yang tidak tahu bahasa masih bisa menulis / mengedit file konfigurasi sederhana menggunakan satu
set name value
pernyataan, sementara pengguna yang lebih maju dan pengembang bisa melakukan trik canggih dengan ini.Saya tidak berpikir bahwa "file konfigurasi bisa menjadi sulit untuk di-debug" adalah masalah yang valid. Selama aplikasi Anda tidak memaksa pengguna untuk menulis skrip, pengguna Anda selalu dapat menggunakan penugasan sederhana dalam file konfigurasi mereka, yang hampir tidak sulit untuk diperbaiki dibandingkan dengan JSON atau XML.
Menulis ulang konfigurasi adalah masalah, meskipun tidak seburuk kelihatannya. Memperbarui kode arbitrer tidak mungkin, tetapi memuat konfigurasi dari file, mengubah dan menyimpannya kembali adalah. Pada dasarnya, jika Anda melakukan beberapa scripting di file konfigurasi yang tidak hanya-baca, Anda hanya akan berakhir dengan daftar
set name value
pernyataan yang setara setelah disimpan. Petunjuk yang baik bahwa ini akan terjadi adalah komentar "jangan edit" di awal file.Satu hal yang perlu dipertimbangkan adalah bahwa file config Anda tidak akan dapat dibaca dengan andal oleh alat sederhana berbasis regex, seperti
sed
, tetapi sejauh yang saya mengerti hal ini tidak terjadi pada file JSON Anda saat ini, jadi tidak ada banyak ruginya.Pastikan Anda menggunakan teknik sandboxing yang tepat saat mengeksekusi file konfigurasi Anda.
sumber
Selain semua poin valid dari jawaban baik lainnya di sini (wow, mereka bahkan menyebutkan konsep Turing-complete), sebenarnya ada beberapa alasan praktis yang kuat untuk TIDAK menggunakan file Python sebagai konfigurasi Anda, bahkan ketika Anda sedang mengerjakan Python- hanya proyek.
Pengaturan di dalam file sumber Python secara teknis merupakan bagian dari kode sumber yang dapat dieksekusi, bukan file data read-only. Jika Anda menggunakan rute ini, biasanya Anda akan melakukannya
import config
, karena "kenyamanan" semacam itu mungkin merupakan salah satu alasan utama orang mulai menggunakan file Python sebagai konfigurasi. Sekarang Anda cenderung untuk memasukkan config.py ke repo Anda, jika tidak, pengguna akhir Anda akan menemukan ImportError yang membingungkan ketika mereka mencoba menjalankan program Anda untuk pertama kalinya.Dengan asumsi Anda benar-benar melakukan konfigurasi itu ke dalam repo Anda, sekarang anggota tim Anda mungkin akan memiliki pengaturan yang berbeda pada lingkungan yang berbeda. Bayangkan suatu hari entah bagaimana beberapa anggota secara tidak sengaja melakukan file konfigurasi lokalnya ke dalam repo.
Terakhir tetapi tidak sedikit, proyek Anda dapat memiliki kata sandi dalam file konfigurasi. (Ini adalah praktik yang dapat diperdebatkan sendiri, tetapi itu tetap terjadi.) Dan jika file konfigurasi Anda ada dalam repo, Anda berisiko melakukan kredensial Anda ke repo publik.
Sekarang, menggunakan file konfigurasi hanya data, seperti format JSON universal, dapat menghindari semua 3 masalah di atas, karena Anda dapat meminta pengguna untuk membuat config.json sendiri dan memasukkannya ke dalam program Anda.
PS: Benar bahwa JSON memiliki banyak batasan. 2 dari keterbatasan yang disebutkan oleh OP, dapat diselesaikan dengan beberapa kreativitas.
Dan saya biasanya memiliki placeholder untuk mengabaikan aturan koma yang tertinggal. Seperti ini:
sumber