2013-09-27 110 views
8

Tôi thích mô-đun argparse. argparse.FileType cũng hữu ích, trừ khi bạn muốn mặc định là một cái gì đó khác hơn sys.std* vì tệp đầu ra mặc định được tạo ngay cả khi bạn cung cấp giá trị .Cách dừng argparse.FileType tạo tệp được chỉ định làm mặc định

Ví dụ:

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

sẽ tạo out.txt ngay cả khi bạn chỉ định một tập tin với --outfile.

Điều tốt nhất tôi có thể đưa ra là:

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 

Nhưng nếu cảm thấy như thế này nên được dễ dàng hơn, tôi thiếu cái gì?

+0

Trong khi tôi thực sự thích câu hỏi của bạn và giải pháp của bạn, tôi không thể tái sản xuất này. Tôi đã tạo một ví dụ nhỏ và khi tôi chỉ định '--outfile', tôi chỉ nhận được tệp mà tôi đã chỉ định được tạo ra chứ không phải cả hai. Bạn đang sử dụng phiên bản python nào? Có lẽ đó là một lỗi trong mô-đun 'argparse' cho một phiên bản nhất định. Tôi đang ở trên 2.7.5 – Brian

+0

Điều đó thật thú vị, @ Brian. [Chương trình này] (http://ideone.com/gC9F0t) khẳng định cài đặt 2.7.3 của tôi và 3.2.3 của tôi. –

+1

có thể trùng lặp của [Chỉ định tên tệp mặc định bằng argparse, nhưng không mở chúng trên --help?] (Http://stackoverflow.com/questions/8236954/specifying-default-filenames-with-argparse-but-not-opening- chúng-on-help) –

Trả lời

3

Có một thay đổi tương đối gần đây trong argparse, http://bugs.python.org/issue12776 (tháng 8 năm 2012), trì hoãn việc đánh giá giá trị mặc định. Ban đầu một chuỗi mặc định sẽ được chuyển qua type (thông qua _get_value) khi bắt đầu phân tích cú pháp, dẫn đến việc mở (và tạo) tệp FileType (cho dù nó có cần thiết hay không). Trong bản vá này, chuỗi được ghi vào Không gian tên, nhưng không được đánh giá cho đến khi kết thúc phân tích cú pháp, khi nó có thể xác định liệu giá trị khác có được cung cấp hay không. Về cơ bản, dòng này đã được chuyển từ sớm parse_known_args đến hết _parse_known_args

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

Trong http://bugs.python.org/issue13824 tôi đã đề nghị một bản vá mà cung cấp một loại FileContext. Sự khác biệt chính của nó từ FileType là nó kết thúc tốt đẹp open(file...) trong một partial. Bằng cách đó, tệp không được mở (hoặc được tạo) cho đến khi thực sự được sử dụng trong ngữ cảnh with args.output() as f:.

Bản vá đó đề cập đến một số thứ khác như kiểm tra xem tệp có thể được tạo hay không (sử dụng os.access) và gói stdin/out trong ngữ cảnh giả để không cố gắng đóng.

Nếu không có thử nghiệm, bạn có thể sửa đổi FileType như thế này:

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