2012-07-18 31 views
35

Şu anda böyle argparse kullanıyorum geçerli değilse:Dosya - hata mesajı argüman

Şimdi
import argparse 
from argparse import ArgumentParser 

parser = ArgumentParser(description="ikjMatrix multiplication") 
parser.add_argument("-i", dest="filename", required=True, 
    help="input file with two matrices", metavar="FILE") 
args = parser.parse_args() 

A, B = read(args.filename) 
C = ikjMatrixProduct(A, B) 
printMatrix(C) 

Ben -i argümanı okunabilir bir dosya olması gerektiğini dikkat etmek istiyorum . Bunu nasıl yapabilirim?

type=open, type=argparse.FileType('r') eklemeye çalıştım ve bunlar işe yaradı, ancak dosya geçerli değilse bir hata iletisi almak istiyorum. Bunu nasıl yapabilirim?

cevap

57

Aslında oldukça kolaydır. Dosyanın geçerli olup olmadığını kontrol eden ve aksi halde bir hata yazan bir işlev yazmanız yeterlidir. Bu işlevi type seçeneği ile kullanın. Daha süslü olabileceğinizi ve argparse.Action alt sınıflarına göre özel bir eylem oluşturabileceğinizi unutmayın, ancak bunun gerekli olduğunu düşünmüyorum. Benim örnekte, bir açık dosya tanıtıcısı döndürür (aşağıya bakınız):

#!/usr/bin/env python 

from argparse import ArgumentParser 
import os.path 


def is_valid_file(parser, arg): 
    if not os.path.exists(arg): 
     parser.error("The file %s does not exist!" % arg) 
    else: 
     return open(arg, 'r') # return an open file handle 


parser = ArgumentParser(description="ikjMatrix multiplication") 
parser.add_argument("-i", dest="filename", required=True, 
        help="input file with two matrices", metavar="FILE", 
        type=lambda x: is_valid_file(parser, x)) 
args = parser.parse_args() 

A, B = read(args.filename) 
C = ikjMatrixProduct(A, B) 
printMatrix(C) 
+0

@moose - Bir başka yorum. 'os.path.isfile', os.path.exists'den daha uygun olabilir (dizinleri de kabul etmek isteyip istemediğinize bağlı olarak) – mgilson

+9

Aslında, bir try-except bloğu ile dosyayı açıp denemek için daha iyi bir uygulama olduğu düşünülürse, Varlığını kontrol etmek için – jarondl

+3

@jarondl haklı. Bu, olası yarış koşullarından kaçınmak için bir “try: ... IOError” hariç, değiştirilmelidir. Çoğu vaka için önemli değil ama bu son zamanlarda beni ısırdı. – AlexLordThorsen

13

Sadece bulduk bu bir:

def extant_file(x): 
    """ 
    'Type' for argparse - checks that file exists but does not open. 
    """ 
    if not os.path.exists(x): 
     # Argparse uses the ArgumentTypeError to give a rejection message like: 
     # error: argument input: x does not exist 
     raise argparse.ArgumentTypeError("{0} does not exist".format(x)) 
    return x 

if __name__ == "__main__": 
    import argparse, sys, os 
    from argparse import ArgumentParser 

    parser = ArgumentParser(description="ikjMatrix multiplication") 
    parser.add_argument("-i", "--input", 
     dest="filename", required=True, type=extant_file, 
     help="input file with two matrices", metavar="FILE") 
    args = parser.parse_args() 

    A, B = read(args.filename) 
    C = ikjMatrixProduct(A, B) 
    printMatrix(C, args.output) 

Kaynak: fhcrc.github.com

+5

'argparse.ArgumentError' yerine' argparse.ArgumentTypeError' komutunu kullanırsanız, ileti yazdırılır. – draganHR

16

Python bunu yapmanın bir yolu 3.4 argparse.FileType sınıfını kullanmaktır. Bitirdiğinizde giriş akışını kapattığınızdan emin olun. Bu da yararlıdır çünkü STDIN/STDOUT için sözde argüman '-' kullanabilirsiniz. belgelerden; FileType nesneleri

Örnek

FileType nesneleri sözde argüman '-' anlamak ve otomatik yazılabilir için okunabilir FileType nesneler için sys.stdin ve sys.stdout içine bu dönüştürmek:

#!/usr/bin/env python3 

import argparse 

if __name__ == '__main__': 
    parser = argparse.ArgumentParser() 
    parser.add_argument('--infile', type=argparse.FileType('r', encoding='UTF-8'), 
         required=True) 
    args = parser.parse_args() 
    print(args) 
    args.infile.close() 

Ve o zaman ...

$ ./stack_overflow.py 
usage: stack_overflow.py [-h] --infile INFILE 
stack_overflow.py: error: the following arguments are required: --infile 
  • varolmayan dosyası ile:

    $ ./stack_overflow.py --infile ./stack_overflow.py 
    Namespace(infile=<_io.TextIOWrapper name='./stack_overflow.py' mode='r' encoding='UTF-8'>) 
    
  • STDIN'den için '-' Kullanılması:

    $ ./stack_overflow.py --infile notme 
    usage: stack_overflow.py [-h] --infile INFILE 
    stack_overflow.py: error: argument --infile: can't open 'notme': [Errno 2] No such file or directory: 'notme' 
    
  • varolan dosyası ile argüman olmadan

    • $ echo 'hello' | ./stack_overflow.py --infile - 
      Namespace(infile=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>) 
      
  • +7

    'argparse.FileType' ayrıca Python 2.7'de kullanılabilir. – jared

    İlgili konular