Seberapa buruk ide untuk menggunakan file Python sebagai file konfigurasi?

72

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.)

André Christoffer Andersen
sumber
39
Tidak terampil bukan masalah Anda. Berbahaya adalah.
Blrfl
9
Apa yang Anda maksud dengan "off the American table" ?
Peter Mortensen
24
"Jadi, untuk saat ini di luar meja Amerika." === "Jadi untuk saat ini, seperti kata orang Amerika, dari meja."
Uskup
7
Jika Anda tidak menyukai JSON, Anda harus mencoba yaml. Saya sangat suka untuk konfigurasi. terutama ketika string yang lebih besar terlibat, YAML lebih mudah dibaca daripada JSON.
Christian Sauer
5
@bishop "off the table" di Inggris Bahasa Inggris berarti tidak lagi dalam pertimbangan, dari mosi parlemen diletakkan di atas meja di tengah-tengah House of Commons untuk referensi ketika sedang dibahas, maka juga 'diajukan untuk diskusi' (Parliamentiary record 1799 - books.google.co.uk/... ), AFAIK artinya AS adalah sama, tapi saya tidak tahu apakah Anda memiliki meja di parlemen Anda.
Pete Kirkham

Jawaban:

92

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 hanya importitu. 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.

amon
sumber
25
Ada beberapa format file konfigurasi yang "sengaja Turing-lengkap", paling terkenal 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 sementara sendmail.cfdapat menghitung fungsi sewenang-wenang, itu tidak dapat mengirim Anda /etc/passwdmelalui net atau memformat harddisk Anda, yang Python atau Perl akan mampu.
Jörg W Mittag
3
@ JörgWMittag Turin-kelengkapan tidak menyiratkan untuk dapat mengirim barang melalui jaringan atau mengakses hard disk. Yaitu, penyelesaian Turin adalah tentang pemrosesan, bukan tentang I / O. Misalnya CSS dianggap Turin lengkap, tetapi tidak akan mengacaukan penyimpanan permanen Anda. Anda telah mengatakan di tempat lain bahwa "Idris adalah bahasa fungsional total murni, jadi menurut definisi tidak lengkap Turing", itu tidak mengikuti, dan tampaknya itu adalah Turin lengkap. Saya yakin Anda menggunakan Testris-complete berarti bahwa bahasa itu adalah Turin lengkap tetapi tidak dapat melakukan I / O penuh ... sepertinya bukan itu yang Anda maksud.
Theraot
6
@Theraot: "Total" berarti selalu kembali. Mesin Turing dapat melakukan loop tak terbatas, yaitu memiliki kemampuan untuk tidak kembali. Ergo, Idris tidak dapat melakukan semua yang dilakukan Mesin Turing, yang berarti Turing tidak lengkap. Ini berlaku untuk semua bahasa yang diketik secara dependen. Inti dari bahasa yang diketik secara dependen adalah bahwa Anda dapat memutuskan properti sewenang-wenang tentang program, sedangkan dalam bahasa Turing-lengkap Anda bahkan tidak bisa memutuskan properti sepele seperti "apakah program ini berhenti?" Total bahasa menurut definisi tidak menyelesaikan Turing, karena Mesin Turing bersifat parsial.
Jörg W Mittag
10
The definisi dari "Turing-lengkap" adalah "dapat menerapkan Turing Machine". Definisi "Tetris-complete" adalah "dapat mengimplementasikan Tetris". Inti dari definisi ini adalah bahwa kelengkapan Turing sama sekali tidak menarik di dunia nyata. Ada banyak bahasa berguna yang tidak menyelesaikan Turing, misalnya HTML, SQL (pra-1999), berbagai DSL, dll. OTOH, Kelengkapan Turing hanya menyiratkan bahwa Anda dapat menghitung fungsi lebih dari angka alami, itu tidak menyiratkan mencetak ke layar, mengakses jaringan, berinteraksi dengan pengguna, OS, lingkungan, yang semuanya penting.
Jörg W Mittag
4
Alasan mengapa Edwin Brady menggunakan contoh ini adalah karena banyak orang berpikir bahwa bahasa yang tidak lengkap Turing tidak dapat digunakan untuk pemrograman tujuan umum. Saya sendiri pernah berpikir demikian, karena bagaimanapun juga, banyak program menarik pada dasarnya adalah loop tanpa akhir yang tidak ingin kita hentikan , misalnya server, sistem operasi, loop acara dalam GUI, loop game. Banyak program memproses data tanpa batas, misalnya aliran acara. Dulu saya berpikir bahwa Anda tidak dapat menulis itu dalam bahasa total, tetapi saya sejak itu mengetahui bahwa Anda bisa , dan jadi saya menemukan ide bagus untuk memiliki istilah untuk kemampuan itu.
Jörg W Mittag
50

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 :)

Celada
sumber
1
@Mast, permintaan maaf, tapi saya tidak mengikutinya. Nama file (apakah berakhir dengan .py) atau tidak ada di sini atau di sana. Poin yang saya coba sampaikan adalah bahwa jika ditulis dengan Python maka Anda memerlukan juru bahasa Python untuk membacanya.
Celada
12
@Mast, saya pikir Anda salah mengartikannya. Poin yang saya ambil dari jawaban ini (baik yang asli maupun yang diedit) adalah bahwa pilihan untuk menulis file konfigurasi dalam bahasa pemrograman adalah membuatnya lebih sulit untuk menulis kode dalam bahasa lain. Misalnya Anda memutuskan untuk port aplikasi Anda ke Anrdoid / iPhone dan akan menggunakan bahasa lain. Anda juga harus (a) mengandalkan juru bahasa Python pada aplikasi ponsel (tidak ideal), (b) menulis ulang konfigurasi dalam format yang bebas bahasa dan menulis ulang kode Python yang menggunakannya, atau (c) memelihara dua format konfigurasi maju.
Jon Bentley
4
@ JonBentley Saya kira kekhawatiran akan relevan jika ada rencana untuk melakukan proyek multi-bahasa. Saya tidak mendapatkan kesan itu dari OP. Selain itu, menggunakan file teks untuk konfigurasi masih memerlukan kode tambahan (dalam semua bahasa) untuk penguraian / konversi nilai aktual. Secara teknis, jika mereka membatasi sisi Python untuk key=valuetugas 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.
code_dredd
3
@ray Benar, tetapi jawabannya tetap berguna karena pertanyaan tidak hanya berlaku bagi orang yang mempostingnya. Jika Anda menggunakan format standar (mis. INI, JSON, YAML, XML, dll.) Maka Anda kemungkinan akan menggunakan parsing library yang sudah ada daripada menulis sendiri. Itu mengurangi pekerjaan tambahan menjadi hanya kelas adaptor untuk berinteraksi dengan parsing library. Jika Anda membatasi diri Anda sendiri ke key = value, maka itu menghilangkan sebagian besar alasan OP untuk menggunakan Python dan Anda mungkin sebaiknya menggunakan format yang dikenali.
Jon Bentley
3
Saya harus melakukan ini beberapa tahun yang lalu ketika alat yang ditulis dalam Lua menggunakan skrip Lua sebagai konfigurasinya, maka mereka ingin kami menulis alat baru dalam C #, dan secara khusus meminta kami untuk menggunakan skrip konfigurasi Lua. Mereka memiliki total 2 baris yang benar-benar dapat diprogram dan tidak sederhana x = y, tetapi saya masih harus belajar tentang open source Lua interpreter untuk .net karena itu. Itu bukan argumen teoretis semata.
Kevin Fee
21

Jawaban lain sudah sangat bagus, saya hanya akan membawa pengalaman penggunaan dunia nyata dalam beberapa proyek.

Pro

Mereka sebagian besar sudah dijabarkan:

  • jika Anda berada dalam program Python, parsing sangat mudah ( 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 melalui repr/ eval);
  • membuat "konfigurasi palsu" hanya dengan beberapa baris kode adalah sepele;
  • Anda memiliki struktur yang lebih baik dan, IMO, sintaks yang jauh lebih baik daripada JSON (ya ampun bahkan hanya memiliki komentar dan tidak harus menempatkan tanda kutip ganda di sekitar kunci kamus adalah kemenangan yang mudah dibaca).

Cons

  • pengguna jahat dapat melakukan apa saja yang bisa dilakukan oleh program utama Anda; Saya tidak menganggap ini sebagai masalah, karena umumnya jika pengguna dapat memodifikasi file konfigurasi, ia sudah dapat melakukan apa pun yang dapat dilakukan aplikasi;
  • jika Anda tidak lagi dalam program Python, sekarang Anda memiliki masalah. Sementara beberapa file konfigurasi kami tetap pribadi untuk aplikasi aslinya, satu file khusus datang untuk menyimpan informasi yang digunakan oleh beberapa program yang berbeda, yang sebagian besar saat ini dalam C ++, yang sekarang memiliki parser yang diretas bersama untuk file kecil yang tidak terdefinisi dengan baik. bagian dari Python repr. Ini jelas hal yang buruk.
  • Bahkan jika program Anda tetap di Python, Anda dapat mengubah versi Python. Katakanlah aplikasi Anda dimulai dengan Python 2; setelah banyak pengujian, Anda berhasil memigrasikannya ke Python 3 - sayangnya, Anda tidak benar - benar menguji semua kode Anda - Anda memiliki semua file konfigurasi yang tergeletak di mesin pelanggan Anda, ditulis untuk Python 2, dan di mana Anda tidak benar-benar memiliki kendali. Anda bahkan tidak dapat memberikan "mode kompatibilitas" untuk membaca file konfigurasi lama (yang sering dilakukan untuk format file), kecuali jika Anda bersedia untuk bundel / panggil juru bahasa Python 2!
  • 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:

    • bahkan hanya melakukan parse → AST → menulis ulang pulang-pergi tidak sepele (Anda akan melihat bahwa separuh dari solusi yang diusulkan kemudian ditandai sebagai "usang, jangan gunakan, tidak bekerja dalam semua kasus");
    • bahkan jika mereka bekerja, AST terlalu rendah; Anda pada umumnya tertarik untuk memanipulasi hasil perhitungan yang dilakukan dalam file, bukan langkah-langkah yang membawanya;
    • yang membawa kita pada fakta sederhana bahwa Anda tidak bisa hanya mengedit nilai yang Anda minati, karena mereka dapat dihasilkan oleh beberapa perhitungan kompleks yang tidak dapat Anda pahami / manipulasi melalui kode Anda.

    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:

    • pasti untuk aplikasi Python dan pribadi untuk itu - seperti, tidak ada orang lain yang pernah mencoba untuk membacanya;
    • tulisan tangan;
    • berasal dari sumber tepercaya;
    • menggunakan tipe data aplikasi target benar-benar premium;

    file Python mungkin merupakan ide yang valid;

  • jika sebaliknya:

    • mungkin ada kemungkinan aplikasi lain membacanya;
    • ada kemungkinan file ini dapat diedit oleh aplikasi, bahkan mungkin aplikasi saya sendiri;
    • disediakan oleh sumber yang tidak dipercaya.

    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.

Matteo Italia
sumber
1
Poin yang sangat bagus tentang membuat atau menulis ulang konfigurasi! Tetapi beberapa format selain XML dapat menyimpan komentar dalam output, yang saya anggap sangat penting untuk konfigurasi. Format lain kadang-kadang memperkenalkan note:bidang yang diabaikan untuk konfigurasi.
amon
2
"jika pengguna dapat memodifikasi file konfigurasi, ia sudah dapat melakukan apa pun yang dapat dilakukan aplikasi" - ini tidak sepenuhnya benar. Bagaimana dengan pengujian daripada file konfigurasi mengkilap yang belum Anda unggah pada pastebin?
Dmitry Grigoryev
2
@DmitryGrigoryev: jika Anda membidik target itu, Anda juga bisa memberi tahu korban Anda untuk menyalin-menempelkan beberapa curl ... | bash, bahkan lebih mudah. :-P
Matteo Italia
@DmitryGrigoryev: dan itu adalah jenis hal yang memungkinkan seseorang untuk sepenuhnya menghancurkan sistem produksi pada hari pertama mereka bekerja. Jika 'eval' adalah parser Anda, itu berarti tidak ada kesempatan untuk memeriksanya sebelum masalah itu dibaca. (alasan yang sama mengapa skrip shell sangat buruk dalam produksi). INI, YAML atau JSON aman dalam hal ini.
Joe
1
@DmitryGrigoryev: maksud saya adalah hanya jika tipe korban Anda cukup bodoh untuk secara sembrono menyalin-tempel file konfigurasi, Anda mungkin bisa menipu dia untuk melakukan apa pun di mesin mereka dengan metode yang tidak terlalu miring ("tempelkan ini ke konsol untuk perbaiki masalah Anda! "). Juga, bahkan dengan file-file konfigurasi yang tidak dapat dieksekusi ada banyak potensi bahaya - bahkan hanya dengan berbahaya mengarahkan logging ke file-file penting (jika aplikasi berjalan dengan cukup privilege) Anda dapat mendatangkan malapetaka pada sistem. Itulah alasan mengapa saya berpikir bahwa dalam praktiknya tidak banyak perbedaan dalam hal keamanan.
Matteo Italia
8

Pertanyaan 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 mainakan (misalnya) menerima beberapa --config argumen confarg dan mendapatkan beberapa FILE*configf;darinya. Jika argumen itu dimulai dengan !(yaitu jika (confarg[0]=='!')....), Anda akan menggunakan configf = popen(confarg+1, "r");dan menutup pipa itu dengan pclose(configf);. Kalau tidak, Anda akan menggunakan configf=fopen(confarg, "r");dan menutup file itu dengan fclose(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.configuntuk melewati ./!foo.configuntuk memotong popentrik 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).

Basile Starynkevitch
sumber
+1 untuk menyebutkan Turing-kelengkapan bahasa pemrograman. Beberapa karya menarik mengungkapkan bahwa membatasi daya komputasi dari format input adalah kunci untuk mengamankan lapisan penanganan input. Menggunakan bahasa pemrograman Turing-complete berjalan ke arah yang berlawanan.
Matheus Moreira
2

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 ConfigParsermodul menerapkan bahasa config sederhana.

CodeMonkey
sumber
1
Menggunakan sesuatu yang 'mirip dengan ... File Microsoft Windows INI' tampaknya merupakan ide yang buruk, keduanya dengan alasan bahwa itu bukan format yang sangat fleksibel, dan karena 'serupa' menyiratkan ketidakcocokan yang tidak berdokumen.
Pete Kirkham
1
@PeteKirkham Yah, sederhana, sudah didokumentasikan, dan itu bagian dari pustaka standar Python. Ini bisa menjadi solusi sempurna untuk kebutuhan OPs, karena dia mencari sesuatu yang didukung langsung oleh Python dan lebih sederhana daripada JSON. Selama dia tidak merinci lebih lanjut apa kebutuhannya, saya pikir jawaban ini mungkin bermanfaat baginya.
CodeMonkey
1
Saya akan menyarankan dasarnya ini - lihat apa jenis file konfigurasi Python libs mendukung dan memilih salah satu dari mereka. Juga, Powershell memiliki gagasan bagian data - yang memungkinkan konstruksi bahasa Powershell terbatas - melindungi terhadap kode berbahaya. Jika Python memiliki lib yang mendukung subset Python terbatas untuk konfigurasi, itu setidaknya mengurangi salah satu kontra terhadap ide di OP.
Χpẘ
1
@PeteKirkham Kemungkinan besar masalah sebaliknya. Windows cenderung memiliki banyak omong kosong tidak berdokumen yang meledak pada Anda. Python cenderung didokumentasikan dengan baik dan langsung. Yang mengatakan, jika Anda semua yang Anda butuhkan adalah pasangan kunci / nilai sederhana ( mungkin dengan bagian), itu adalah pilihan yang cukup bagus. Saya menduga ini mencakup 90% kasus penggunaan. Jika file .NET konfigurasi ini bukan XML mengerikan dengan skema yang sebenarnya menyamar sebagai konfigurasi, kita semua akan jauh lebih baik.
jpmc26
1
@PeteKirkham Tidak juga. INI menjadi yang terbaik untuk kasus penggunaan sederhana, kemungkinan Anda dapat menghindari ketidaksesuaian. Mereka juga tidak masalah jika Anda tidak menggunakan file dengan dua bahasa yang berbeda, dan bahkan jika Anda melakukannya, Anda mungkin dapat menemukan implementasi terbuka dalam bahasa apa pun (memungkinkan Anda untuk tidak memiliki ketidaksesuaian atau, setidaknya, tahu persis apa mereka). Saya setuju bahwa Anda harus menggunakan format lain jika use case Anda sebenarnya cukup kompleks sehingga Anda mulai berlari ke dalamnya atau jika Anda tidak dapat menemukan implementasi yang dapat Anda percayai, tetapi itu tidak umum.
jpmc26
1

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 valuepernyataan, 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 valuepernyataan 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.

Dmitry Grigoryev
sumber
1
"Perangkat lunak" adalah kata benda yang tidak terhitung, sehingga harus " beberapa perangkat lunak yang terkenal."
jpmc26
1

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.

  1. 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.

  2. 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.

  3. 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.

RayLuo
sumber