2009-08-28 27 views
5

我正在開發一個管理腳本,它通過大量的命令行選項執行相當大量的工作。腳本的前幾次迭代使用optparse來收集用戶輸入,然後在頁面上運行,按照適當的順序測試每個選項的值,並在必要時執行操作。這導致了一堆難以閱讀和維護的代碼。命令行arg通過自省進行解析

我正在尋找更好的東西。我希望有一個系統,我可以用或多或少的普通Python方式編寫函數,然後當腳本運行時,從我的函數生成選項(和幫助文本),解析並執行適當的順序。此外,我真的希望能夠建立的Django風格的子命令接口,其中myscript.py install作品完全分開myscript.py remove(不同的選項,幫助等)

我發現simon willison's optfunc,並做了很多這個,但似乎只是錯過了標記 - 我想寫每個選項作爲一個函數,而不是試圖將整個選項集壓縮成一個巨大的選項集。

我想象一個架構涉及一組主要功能的類,並且每個定義的類的方法都對應於命令行中的一個特定選項。這種結構提供了將每個選項駐留在其修改的功能代碼附近的優點,從而簡化了維護。我不知道如何處理的是命令的排序,因爲類方法的排序不是確定性的。

在我重新發明車輪之前:是否還有其他現有的代碼行爲類似?其他事情很容易修改?問這個問題澄清了我自己對什麼是好的想法,但是爲什麼這是一個可怕的想法或者它應該如何工作的反饋是值得歡迎的。

回答

4

不要浪費時間在「自省」上。

每個「命令」或「選項」是具有兩組方法功能或屬性的對象。

  1. 向optparse提供設置信息。

  2. 其實做這項工作。

這裏的父類中的所有命令

class Command(object): 
    name= "name" 
    def setup_opts(self, parser): 
     """Add any options to the parser that this command needs.""" 
     pass 
    def execute(self, context, options, args): 
     """Execute the command in some application context with some options and args.""" 
     raise NotImplemented 

你爲InstallRemove,你需要每隔命令創建sublcasses。

您的整體應用程序看起來像這樣。

commands = [ 
    Install(), 
    Remove(), 
] 
def main(): 
    parser= optparse.OptionParser() 
    for c in commands: 
     c.setup_opts(parser) 
    options, args = parser.parse() 
    command= None 
    for c in commands: 
     if c.name.startswith(args[0].lower()): 
      command= c 
      break 
    if command: 
     status= command.execute(context, options, args[1:]) 
    else: 
     logger.error("Command %r is unknown", args[0]) 
     status= 2 
    sys.exit(status) 
+0

謝謝,這似乎是很好的建議。 – 2009-08-30 14:22:57

+0

這很棒! – 2017-09-27 21:12:38

0

的WSGI庫WERKZEUG提供Management Script Utilities可以做你想做的,或者至少給你一個提示如何自己做了反省。

from werkzeug import script 

# actions go here 
def action_test(): 
    "sample with no args" 
    pass 

def action_foo(name=2, value="test"): 
    "do some foo" 
    pass 

if __name__ == '__main__': 
    script.run() 

這將產生以下幫助信息:

$ python /tmp/test.py --help 
usage: test.py <action> [<options>] 
     test.py --help 

actions: 
    foo: 
    do some foo 

    --name      integer 2 
    --value      string test 

    test: 
    sample with no args 

動作是開始「action_」,這需要數量的參數,每一個參數都有一個默認的相同的模塊中的功能。默認值的類型指定參數的類型。

然後可以通過位置或使用shell中的--name = value傳遞參數。