2013-09-27 7 views
8

Mi piace il modulo argparse. argparse.FileType è utile anche se non si desidera che il valore predefinito sia diverso da sys.std* poiché viene creato il file di output predefinito anche se si fornisce un valore .Come arrestare argparse.FileType creando il file specificato come predefinito

Ad esempio:

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

creerà out.txt anche se si specifica un file con --outfile.

Il meglio che posso venire in mente è:

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 

Ma se si sente come questo dovrebbe essere più facile, mi sto perdendo qualcosa?

+0

Mentre mi piace molto la tua domanda e la soluzione, non riesco a riprodurre questo. Ho fatto un piccolo esempio e, quando specifico '--outfile', ottengo solo il file che ho specificato, non entrambi. In che versione di pitone sei? Forse è un bug nel modulo 'argparse' per una certa versione. Sono al 2.7.5 – Brian

+0

È interessante, @ Brian. [Questo programma] (http://ideone.com/gC9F0t) asserisce sulla mia installazione 2.7.3 e sul mio 3.2.3. –

+1

possibile duplicato di [specificare nomi file predefiniti con argparse, ma non aprirli su --help?] (Http://stackoverflow.com/questions/8236954/specifying-default-filenames-with-argparse-but-not-opening- it-on-help) –

risposta

3

C'è stata una variazione relativamente recente in argparse, http://bugs.python.org/issue12776 (agosto 2012), che ritarda la valutazione del valore predefinito. Originariamente una stringa predefinita veniva passata attraverso type (tramite _get_value) all'inizio dell'analisi, determinando l'apertura (e la creazione) di un file FileType (se necessario o meno). In questa patch, la stringa viene scritta nello spazio dei nomi, ma non viene valutata fino alla fine dell'analisi, quando può determinare se è stato fornito o meno un altro valore. Fondamentalmente, questa linea è stata spostata dalle prime parse_known_args alla fine _parse_known_args

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

In http://bugs.python.org/issue13824 ho proposto una patch che fornisce un tipo FileContext. La sua differenza principale da FileType è che avvolge il open(file...) in un partial. In questo modo il file non viene aperto (o creato) fino a quando non viene effettivamente utilizzato in un contesto with args.output() as f:.

Questa patch si occupa di altre cose come testare se il file può essere creato o meno (utilizzando os.access) e il wrapping di stdin/out in un contesto fittizio in modo che non tenti di chiuderlo.

Senza di test, è possibile modificare FileType come questo:

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') 
Problemi correlati