2014-04-10 30 views
9

Đoạn mã sau, bằng cách sử dụng subparsers của argparse, thất bại trên Python 3 nhưng chạy như mong đợi trong Python 2. Sau khi so sánh các tài liệu, tôi vẫn không thể nói tại sao.Tại sao mã argparse này hoạt động khác nhau giữa Python 2 và 3?

#!/usr/bin/env python 
from __future__ import print_function 
from argparse import ArgumentParser 


def action(args): 
    print(args) 

if __name__ == '__main__': 
    std = ArgumentParser(add_help=False) 
    std.add_argument('standard') 

    ap = ArgumentParser() 
    sp = ap.add_subparsers() 

    cmd = sp.add_parser('subcommand', parents=[std], description='Do subcommand') 
    cmd.add_argument('arg') 
    cmd.set_defaults(do=action) 

    args = ap.parse_args() 
    args.do(args) 

Kết quả từ Python 2.7.6 là:

[email protected]$ python test.py 
usage: test.py [-h] {subcommand} ... 
test.py: error: too few arguments 

Trong Python 3.3.5, tôi nhận được:

[email protected]$ python3 test.py 
Traceback (most recent call last): 
    File "test.py", line 21, in <module> 
    args.do(args) 
AttributeError: 'Namespace' object has no attribute 'do' 
+0

Lưu ý rằng nếu bạn sử dụng một subparser: 'args = cmd.parse_args()' nó sẽ hoạt động. – alecxe

+0

Mã này dường như cung cấp cho cùng một lỗi cho tôi trên Python 2.7.4. Nhiều khả năng bạn đang chạy phiên bản tệp sai hoặc một cái gì đó. Nó không nên hoạt động. Hãy thử lại cẩn thận hơn. – bosnjak

+0

Khi tôi gõ mã của bạn tại một thông dịch viên Python 2.7.6, tôi nhận được cùng một lỗi tại dòng 'args = ap.parse_args()'. –

Trả lời

12

phiên bản mới nhất argparse thay đổi như thế nào nó kiểm tra cho các đối số cần thiết , và các subparsers rơi qua các vết nứt. Chúng không còn 'bắt buộc' nữa. http://bugs.python.org/issue9253#msg186387

Khi bạn nhận được test.py: error: too few arguments, điều đó phản đối rằng bạn không cho nó một đối số 'đại diện'. Trong 3.3.5 nó làm cho nó qua bước đó, và trả về args.

Với thay đổi này, 3.3.5 nên cư xử giống như phiên bản trước:

ap = ArgumentParser() 
sp = ap.add_subparsers(dest='parser') # dest needed for error message 
sp.required = True # force 'required' testing 

Lưu ý - cả destrequired cần phải được thiết lập. Cần có dest để đặt cho đối số này một tên trong thông báo lỗi.


lỗi này:

AttributeError: 'Namespace' object has no attribute 'do' 

được sản xuất bởi vì cmd subparser không chạy, và không đưa đối số của nó (mặc định hay không) vào không gian tên. Bạn có thể thấy hiệu ứng đó bằng cách xác định một subparser khác, và xem kết quả args.

+1

Cảm ơn, đã đóng đinh nó. Trong trường hợp có bất kỳ thắc mắc nào, giải pháp này tương thích ngược với Python 2.7 – Wedgwood

Các vấn đề liên quan