1. 程式人生 > 其它 >無效的過程呼叫或引數_python中關於傳遞引數模組argprase的一些小坑

無效的過程呼叫或引數_python中關於傳遞引數模組argprase的一些小坑

技術標籤:無效的過程呼叫或引數

abcc9739e183b937576440199468d345.png

今天在寫程式碼的時候遇到了一個關於parser的一些小坑,記錄在此備用。

我們知道在python中可以用argprase來傳遞一些引數給程式碼執行,來看下面的例子,假設現在有一個test資料夾,下面有3個python檔案,分別用a.py;b.py;c.py來表示,目錄樹如下。

22421c2e12d26fbb6fc2df22678cb750.png

每一個的初始程式碼為一個簡單的print函式。

# a.py
def out_a():
    print("I am a.py")


if __name__ == '__main__':
    out_a()



# b.py
def out_b():
    print("I am b.py")


if __name__ == '__main__':
    out_b()



# c.py
def out_c():
    print("I am c.py")


if __name__ == '__main__':
    out_c()

現在在a.py中引入模組argprase,並定義一些簡單的引數,程式碼如下:

# a.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--first_parameter', default='first')
parser.add_argument('--second_parameter', default='second')
parser.add_argument('--third_flag', action='store_true')
args = parser.parse_args()
print(args)


def out_a():
    print("I am a.py")


if __name__ == '__main__':
    out_a()

這裡面簡單說一下第3個引數,這也是我今天想記錄文章的原因,這個引數是argparse裡面提供的開關布林選項,actions記錄的是一個動作,意味著在呼叫這個函式的時候,如果在命令列新增這個引數,則該引數為True,如果不新增這個引數,則該引數為False,歸納起來為如下的兩個圖。

135df1cc258e03ff0d9b77d4c9057c4d.png
沒有呼叫第3個引數的情況

ef5eb82caf39cc8114f75ec8cf7fbf84.png
呼叫第3個引數的情況

對於這種開關布林選項更為詳細的介紹,可以參考知乎問題:

Argparse中action的可選引數store_true,store_false到底是什麼意思?​www.zhihu.com

到目前為止沒有出現問題,接下來,我希望b.py也使用引數,並且還希望使用a.py裡面的函式,因此我對b.py進行如下修改。

from a import out_a
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--fourth_parameter', default='fourth')
parser.add_argument('--fifth_parameter', default='fifth')
parser.add_argument('--sixth_flag', action='store_true')
args = parser.parse_args()


def out_b():
    print("I am b.py")


if __name__ == '__main__':
    out_b()
    out_a()

然後同樣的,我們分別用兩種方式來測試b.py,效果如下。

8a96652e1c0adb273068dec21b5fbde8.png
沒有呼叫第3個引數,一切正常

c6199d49e8e4d301accc56e9604a1e89.png
呼叫第3個引數,報錯了

當時我看到這裡的時候想了很久,排除了拼寫錯誤的情況以後,觀察這裡面的輸出,發現看到的是a.py當中的3個引數,而不是b.py當中設定的引數,於是我將a.py和b.py的引數表打印出來,看到這樣子的結果。

4345c9177233159610072761adb92f02.png
輸出引數表的情況

可以發現儘管我使用的是from a import out_a,但依然引入了a.py當中的引數表,並且後引入的b.py的引數表沒有辦法覆蓋掉。下面在c.py中同樣引入3個引數,然後引入b.py的方法,程式碼如下:

from b import out_b
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--seventh_parameter', default='seventh')
parser.add_argument('--eighth_parameter', default='eighth')
parser.add_argument('--ninth_flag', action='store_true')
args = parser.parse_args()
print(args)


def out_c():
    print("I am c.py")


if __name__ == '__main__':
    out_c()
    out_b()

效果如下

4c63084dfa8d49eecd8e9087387bdbf8.png
沒有使用第3個引數的情況

看到有3個引數列表輸出就知道c.py的引數也是無效的了,驗證一下。

937075f115654b4f0f4027d70a1793f6.png
使用第3個引數的情況

解決方案:

其實只需要將所有的引數表放到同一個檔案裡面就可以了,比如utils.py,由於這裡是同一個資料夾下的3個檔案,在import呼叫的時候就只需要初始化一次所有引數就可以使用了,有點類似於C語言當中的全域性變數,因為這個東西排查了一個多小時,也是有點惱火了。

最後賣一下我的部落格......

JCChan - 部落格園​www.cnblogs.com