1. 程式人生 > >tf.app.flags.DEFINE_string()和tf.app.flags.FLAGS

tf.app.flags.DEFINE_string()和tf.app.flags.FLAGS

在看SSD的TensorFlow原始碼(連結點選開啟連結)時遇到了這tf.app.flags.DEFINE_string()函式和tf.app.flags.FLAGS變數,於是翻閱TensorFlow官網API結果竟然是。。。

真是相當於白說,意思還是讓我自己看原始碼。。。。。。。

於是上網找,還是找到了Stack Overflow裡的一個解答點選開啟連結


答案說其實這個,很多時候看TensorFlow的API文件不如看TensorFlow的原始碼更容易(真的麼。。。),所以答主經常用pycharm開啟TensorFlow原始碼的工程,這樣能方便的找到答案。比如說你看要看tensorflow/python/platform/flags.py

其實是個披著很薄的裝飾的argparse.ArgumentParse()(什麼是python的argparse,請看這裡點選開啟連結),所以也還是得看python的argparse的API文件。

好吧,在我辛苦弄懂argparse也就是一個方便使用者新增命令列的玩意之後,問題終於明瞭了。

我抽取了flags.py的幾段程式

這裡是import了argparse as _argparse


然後建立argparse一個全域性物件_global_parser


定義了_FlagValues這個類,並使用前面定義的全域性物件_global_parser,將_global_parser裡得到的命令列解析出來,使用了parse_known_args()這個函式(具體可從這裡檢視

點選開啟連結)返回一個有用的result,和一個無用的unparsed,後面再使用迭代,將命令列傳入的命令和資料解析出來以字典的形式放到__dict__的['_flags']這個字典中,這樣當要訪問命令列輸入的命令時,就能使用像tf.app.flag.Flags(Flags後面會提到,是_FlagValues這個類的一個例項)這樣的命令了


然後後面在_define_helper函式中呼叫了_global_parser.add_argument完成對命令列option argument的新增,這裡呼叫_global_parser也就是前面引數解析器的一個例項,也就是說,真正完成對命令列引數新增的是在_define_helper中的_global_parser.add_argument函式,仔細看這個函式的引數,第一個引數時 ‘--’+flag_name這個表示我們定義的命令列引數使用時必須以 ‘--’開頭,比如‘--flag_int 9’(具體看後面栗子),而第二個引數是命令列的預設值,因為有時候並沒有賦給命令列引數值,這個時候就預設值就發揮作用了,而第三個引數help儲存幫助資訊(具體可看後面栗子),第四個引數表示限定了賦予命令列引數資料的型別。


看DEFINE_string(),這裡則由於_define_helper()最後一個type引數時str,上面我們關於_define_helper的引數的解釋,說明DEFINE_string()限定了可選引數輸入必須是string,這也就是為什麼這個函式定義為DEFINE_string(),同理,DEFINE_int()限定可選引數必須是int,DEFINE_float()限定可選引數必須是float,DEFINE_boolean()限定可選引數必須是bool。


最關鍵的一步,這裡定義了_FlagValues這個類的一個例項,這樣的這樣當要訪問命令列輸入的命令時,就能使用像tf.app.flag.Flags這樣的操作。


感覺說得很零碎,總結起來的話,tf.app.flags.DEFINE_xxx()就是新增命令列的optional argument(可選引數),而tf.app.flags.FLAGS可以從對應的命令列引數取出引數。

舉個栗子

新建test.py檔案,並輸入如下程式碼,程式碼的功能是建立幾個命令列引數,然後把命令列引數輸出顯示

import tensorflow  as tf
FLAGS=tf.app.flags.FLAGS
tf.app.flags.DEFINE_float(
    'flag_float', 0.01, 'input a float')
tf.app.flags.DEFINE_integer(
    'flag_int', 400, 'input a int')
tf.app.flags.DEFINE_boolean(
    'flag_bool', True, 'input a bool')
tf.app.flags.DEFINE_string(
    'flag_string', 'yes', 'input a string')

print(FLAGS.flag_float)
print(FLAGS.flag_int)
print(FLAGS.flag_bool)
print(FLAGS.flag_string)


1.在命令列中檢視幫助資訊,在命令列輸入 python test.py -h


注意紅色框中的資訊,這個就是我們用DEFINE_XXX新增命令列引數時的第三個引數

2.直接執行test.py


因為沒有給對應的命令列引數賦值,所以輸出的是命令列引數的預設值。

3.帶命令列引數的執行test.py檔案


這裡輸出了我們賦給命令列引數的值