Saya tahu --verbose
atau -v
dari beberapa alat dan saya ingin menerapkan ini ke dalam beberapa skrip dan alat saya sendiri.
Saya berpikir untuk menempatkan:
if verbose:
print ...
melalui kode sumber saya, sehingga jika pengguna melewati -v
opsi, variabel verbose
akan disetel ke True
dan teks akan dicetak.
Apakah ini pendekatan yang tepat atau ada cara yang lebih umum?
Penambahan: Saya tidak meminta cara untuk mengimplementasikan parsing argumen. Bahwa saya tahu bagaimana hal itu dilakukan. Saya hanya tertarik secara khusus pada opsi verbose.
Jawaban:
Saran saya adalah menggunakan suatu fungsi. Tetapi alih-alih memasukkan
if
fungsi, yang mungkin Anda tergoda untuk melakukannya, lakukan seperti ini:if verbose: def verboseprint(*args): # Print each argument separately so caller doesn't need to # stuff everything to be printed into a single string for arg in args: print arg, print else: verboseprint = lambda *a: None # do-nothing function
(Ya, Anda dapat menentukan fungsi dalam
if
pernyataan, dan itu hanya akan ditentukan jika kondisinya benar!)Jika Anda menggunakan Python 3, di mana
print
sudah menjadi fungsi (atau jika Anda ingin menggunakanprint
sebagai fungsi di 2.x menggunakanfrom __future__ import print_function
) itu bahkan lebih sederhana:verboseprint = print if verbose else lambda *a, **k: None
Dengan cara ini, fungsi didefinisikan sebagai tidak melakukan apa-apa jika mode verbose tidak aktif (menggunakan lambda), alih-alih terus-menerus menguji
verbose
flag.Jika pengguna dapat mengubah mode verbositas selama menjalankan program Anda, ini akan menjadi pendekatan yang salah (Anda memerlukan
if
fungsi in), tetapi karena Anda menyetelnya dengan panji baris perintah, Anda hanya perlu buat keputusan sekali.Anda kemudian menggunakan mis
verboseprint("look at all my verbosity!", object(), 3)
kapan pun Anda ingin mencetak pesan "verbose".sumber
print
fungsi: Terima banyak argumen. Ini dapat diimplementasikan sepertiprint(*args)
di 3.x danfor arg in args: print arg,
di 2.x. Keuntungan utama adalah memungkinkan pencampuran string dan hal-hal dari jenis lain dalam satu pesan tanpastr
panggilan / pemformatan dan penggabungan eksplisit .print arg,
baris?def verboseprint(*args, **kwargs): print(*args, **kwargs)
Gunakan
logging
modul:import logging as log … args = p.parse_args() if args.verbose: log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG) log.info("Verbose output.") else: log.basicConfig(format="%(levelname)s: %(message)s") log.info("This should be verbose.") log.warning("This is a warning.") log.error("This is an error.")
Semua ini otomatis masuk ke
stderr
:Untuk info lebih lanjut, lihat Python Docs dan tutorialnya .
sumber
Membangun dan menyederhanakan jawaban @ kindall, inilah yang biasanya saya gunakan:
v_print = None def main() parser = argparse.ArgumentParser() parser.add_argument('-v', '--verbosity', action="count", help="increase output verbosity (e.g., -vv is more than -v)") args = parser.parse_args() if args.verbosity: def _v_print(*verb_args): if verb_args[0] > (3 - args.verbosity): print verb_args[1] else: _v_print = lambda *a: None # do-nothing function global v_print v_print = _v_print if __name__ == '__main__': main()
Ini kemudian memberikan penggunaan berikut di seluruh skrip Anda:
v_print(1, "INFO message") v_print(2, "WARN message") v_print(3, "ERROR message")
Dan skrip Anda bisa disebut seperti ini:
Beberapa catatan:
3
yang menetapkan batas atas untuk logging Anda, tetapi saya menerimanya sebagai kompromi untuk kesederhanaan.v_print
bekerja di seluruh program Anda, Anda harus melakukan sampah dengan global. Ini tidak menyenangkan, tapi saya menantang seseorang untuk menemukan cara yang lebih baik.sumber
-v
digunakan. Dalam solusi Anda saat ini semuanya dibuang ke stdout bukan stderr. Dan: Anda biasanya ingin menyampaikan setiap kesalahan kepada pengguna, bukan?Apa yang saya lakukan di skrip saya adalah memeriksa saat runtime jika opsi 'verbose' disetel, lalu setel tingkat logging saya ke debug. Jika tidak disetel, saya setel ke info. Dengan cara ini Anda tidak memiliki pemeriksaan 'if verbose' di seluruh kode Anda.
sumber
Mungkin lebih bersih jika Anda memiliki fungsi, katakanlah dipanggil
vprint
, yang memeriksa tanda verbose untuk Anda. Kemudian Anda cukup memanggilvprint
fungsi Anda sendiri di mana pun Anda ingin verbositas opsional.sumber
Saya mencuri kode logging dari virtualenv untuk proyek saya. Lihat di
main()
darivirtualenv.py
untuk melihat bagaimana hal itu diinisialisasi. Kode ini ditaburi denganlogger.notify()
,logger.info()
,logger.warn()
, dan sejenisnya. Metode sebenarnya keluaran memancarkan ditentukan oleh apakah virtualenv itu dipanggil dengan yang-v
,-vv
,-vvv
, atau-q
.sumber
Solusi @ kindall tidak berfungsi dengan Python versi 3.5 saya. @styles dengan benar menyatakan dalam komentarnya bahwa alasannya adalah argumen kata kunci opsional tambahan . Oleh karena itu versi saya yang sedikit disempurnakan untuk Python 3 terlihat seperti ini:
if VERBOSE: def verboseprint(*args, **kwargs): print(*args, **kwargs) else: verboseprint = lambda *a, **k: None # do-nothing function
sumber
Mungkin ada variabel global, kemungkinan diatur dengan
argparse
fromsys.argv
, yang menunjukkan apakah program harus bertele-tele atau tidak. Kemudian dekorator dapat ditulis sedemikian rupa sehingga jika verbositas aktif, maka input standar akan dialihkan ke perangkat null selama fungsinya berjalan:import os from contextlib import redirect_stdout verbose = False def louder(f): def loud_f(*args, **kwargs): if not verbose: with open(os.devnull, 'w') as void: with redirect_stdout(void): return f(*args, **kwargs) return f(*args, **kwargs) return loud_f @louder def foo(s): print(s*3) foo("bar")
Jawaban ini terinspirasi oleh kode ini ; sebenarnya, saya hanya akan menggunakannya sebagai modul dalam program saya, tetapi saya mendapat kesalahan yang tidak dapat saya pahami, jadi saya menyesuaikan sebagian darinya.
Kelemahan dari solusi ini adalah bahwa verbositas adalah biner, tidak seperti with
logging
, yang memungkinkan penyetelan yang lebih baik tentang seberapa panjang program tersebut. Selain itu, semuaprint
panggilan dialihkan, yang mungkin tidak diinginkan.sumber
Yang saya butuhkan adalah fungsi yang mencetak objek (obj), tetapi hanya jika variabel global verbose benar, jika tidak, ia tidak melakukan apa-apa.
Saya ingin dapat mengubah parameter global "verbose" kapan saja. Kesederhanaan dan keterbacaan bagi saya adalah yang terpenting. Jadi saya akan melanjutkan seperti yang ditunjukkan baris berikut:
ak@HP2000:~$ python3 Python 3.4.3 (default, Oct 14 2015, 20:28:29) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>> verbose = True >>> def vprint(obj): ... if verbose: ... print(obj) ... return ... >>> vprint('Norm and I') Norm and I >>> verbose = False >>> vprint('I and Norm') >>>
Variabel global "verbose" juga dapat disetel dari daftar parameter.
sumber