2013-09-27 9 views
8

Uwielbiam moduł argparse. Pomocne jest również argparse.FileType, chyba że chcesz, aby wartość domyślna była inna niż sys.std*, ponieważ tworzony jest domyślny plik wyjściowy, nawet jeśli podasz wartość .Jak zatrzymać argparse.FileType tworząc plik określony jako domyślny

Na przykład:

parser.add_argument('--outfile', type=FileType('w'), default="out.txt") 

stworzy out.txt nawet jeśli określony plik z --outfile.

Najlepszym mogę wymyślić jest:

class MagicFileType(object): 

    def __init__(self, *args, **kwargs): 

     # save args/kwargs and set filetype to None 
     self.filetype = None 
     self.args = args 
     self.kwargs = kwargs 

    def __getattr__(self, attr): 
     """ Delegate everything to the filetype """ 

     # If we haven't created it, now is the time to do so 
     if self.filetype is None: 
      self.filetype = FileType(*self.args, **self.kwargs) 
      self.filetype = self.filetype(self.filename) 

     return getattr(self.filetype, attr) 

    def __call__(self, filename): 
     """ Just cache the filename """ 

     # This is called when the default is created 
     # Just cache the filename for now. 
     self.filename = filename 
     return self 

Ale jeśli czuje się jak to powinno być łatwiej, ja czegoś brakuje?

+0

Chociaż bardzo lubię swoje pytanie i rozwiązanie, nie mogę odtworzyć tego. Zrobiłem mały przykład, a kiedy podam '--outfile', otrzymam tylko plik określony przeze mnie, a nie oba. Jakiej wersji python się używasz? Może to błąd w module 'argparse' dla pewnej wersji. Jestem na 2.7.5 – Brian

+0

To interesujące, @ Brian. [Ten program] (http://ideone.com/gC9F0t) potwierdza moją instalację 2.7.3 i moją 3.2.3. –

+1

możliwy duplikat [Określanie domyślnych nazw plików z argparse, ale nie otwieranie ich na --help?] (Http://stackoverflow.com/questions/8236954/specifying-default-filenames-with-argparse-but-not-opening- one-on-help) –

Odpowiedz

3

Nastąpiła stosunkowo niedawna zmiana w argparse, http://bugs.python.org/issue12776 (sierpień 2012), która opóźnia ocenę wartości domyślnej. Pierwotnie domyślna wartość ciągu byłaby przekazywana przez type (przez _get_value) na początku parsowania, powodując otwarcie (i utworzenie) pliku FileType (bez względu na to, czy byłby potrzebny, czy nie). W tej poprawce łańcuch jest zapisywany w przestrzeni nazw, ale nie jest analizowany do końca analizowania, gdy może określić, czy podano inną wartość, czy nie. Zasadniczo, linia ta została przeniesiona z początku parse_known_args do końca _parse_known_args

default = self._get_value(action, action.default) 

W http://bugs.python.org/issue13824 I zaproponował poprawkę, która przewiduje typ FileContext. Główną różnicą w stosunku do FileType jest zawijanie open(file...) w postaci partial. W ten sposób plik nie zostanie otwarty (lub utworzony), dopóki nie zostanie użyty w kontekście with args.output() as f:.

Ta łatka dotyczy kilku innych rzeczy, takich jak testowanie, czy plik można utworzyć, czy nie (przy użyciu os.access) i zawijanie stdin/out w fikcyjnym kontekście, więc nie próbuje go zamknąć.

Bez testów, można modyfikować FileType takiego:

class FileOpener(argparse.FileType): 
    # delayed FileType; 
    # sample use: 
    # with args.input.open() as f: f.read() 
    def __call__(self, string): 
     # optionally test string 
     self.filename = string 
     return self 
    def open(self): 
     return super(FileOpener,self).__call__(self.filename) 
    file = property(open, None, None, 'open file property') 
Powiązane problemy