2012-04-09 34 views
6

Sau khi chuyển từ optparse sang argparse - Tôi gặp phải lỗi lạ. Argparse phân tích args chỉ khi rời khỏi không gian:Python: chuyển từ optparse sang argparse

myScript.py -oOpt 

hoặc đặt một dấu bằng:

myScript.py -o=Opt 

và nó không hoạt động theo cách thông thường:

myScript.py -o Opt 

Dưới đây là khởi argparse của tôi :

#!/usr/bin/env python 
# to get description use the -h flag 

import argparse, os, sys 


# ====================== 
# Python2.7 is expected: 

if sys.version_info[0] != 2 or sys.version_info[1] < 7: 
    sys.exit('This program needs Python2.7+') 


# ========== 
# preambule: 

desc = """Enter dirs in the current dir and makes gro out of state.cpt there.""" 
# parser = argparse.ArgumentParser() 
parser = argparse.ArgumentParser(description=desc, version='2.3', formatter_class=argparse.ArgumentDefaultsHelpFormatter) 
parser.add_argument('-w', '--workWith', 
        help = 'to specify a Gromacs exec suffix', 
        dest = 'wW', 
        action = 'store', 
        default = '-4.5.5-single', 
        ) 
parser.add_argument('-g', '--gro', 
        help = '.gro postfix: <nameOfTheDir><postfix>.gro', 
        dest = 'myGroPostfix', 
        action = 'store', 
        default = "_membrane", 
        ) 
parser.add_argument('-H', '--here', 
        help = 'toggles - single (current) dir behaviour (the output will be state.gro)', 
        dest = 'Here', 
        action = 'store_true', 
        ) 
parser.add_argument('-D', '--dirs', 
        help = 'include these dirs (python\'s rgxp in SINGLE quotes), defaults to \'\'', 
        dest = 'inclDirs', 
        action = 'store', 
        default = '', 
        ) 

args = parser.parse_args() 


print args.wW 

Sửa:

Thậm chí nhiều hơn:

gmx_bk-simulate-mems.py -j bk-runs-mpi.bash -p 1 -w="-4.5.5-double_non-parallel_gcc" 2&> ../`date +%Y-%b-%d-%H%M%S`.log & 

cho:

gmx_bk-simulate-mems.py: error: unrecognized arguments: 2 

nó trông giống như argparse xử lý 2&> như tùy chọn (hoặc 2&>../date +%Y-%b-%d-%H%M%S.log như tùy chọn)!

Chỉnh sửa 2:

Vì vậy, để tóm tắt:

  • Đối argparse-"-4.5.5-double_non-parallel_gcc" là một cái tên tùy chọn xấu - và đó là lý do tại sao nó là cần thiết để viết là như -w="-4.5.5-double_non-parallel_gcc". Đối với optparsebash (!) Điều này là tốt. bash thậm chí có lỗi tại -w="-4.5.5-double_non-parallel_gcc" - nó cho rằng arg là ="-4.5.5-double_non-parallel_gcc" (!);

  • Không có điều nào như 2&>. 2> có thể được sử dụng và không có lỗi;

  • Đây là shell người chia dòng thành args, chứ không phải python;

  • argparse tốt hơn nhiều so với optparse.

+0

Đặt mã của bạn trong 'tmp.py', cả hai 'python tmp.py -w3' và' python tmp.py -w 3' in' 3 'cho tôi. – chepner

+0

@chepner: vâng ... thực ra vấn đề cho dòng 75 trong [gmx_bk-get-results.bash] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-get-results .bash): nếu một người loại bỏ '=' khỏi dòng đó - tập lệnh đưa ra lỗi - như thể tôi không cho nó '" $ wW "'. Để tái tạo một nhu cầu cũng phải nhận được [bk-copies-from-dirs.py] (https://github.com/bk322/bk-goodies/blob/master/bk-copies-from-dirs.py) và [gmx_bk-cpt2gmx.py] (https://github.com/bk322/bk-bio/blob/master/gmx_bk-cpt2gmx.py) ... Mọi thứ đều hoạt động tốt trên 'optparse'. Tôi hy vọng ai đó sẽ thấy vấn đề "về mặt lý thuyết". – Adobe

+1

Nhận xét giả tạo: Bạn không cần trình kiểm tra phiên bản. Nếu bạn sử dụng Python 3, câu lệnh in ở phía dưới sẽ gây ra lỗi cú pháp và tập lệnh sẽ không được tải. Nếu bạn sử dụng Python 2.6 hoặc thấp hơn, tập lệnh sẽ thất bại khi nhập 'argparse', trước khi bạn thậm chí có thể kiểm tra phiên bản. – HardlyKnowEm

Trả lời

12

Trước tiên, cần phân biệt nhỏ. Mô-đun argparse không phân tích đối số dòng lệnh của bạn, trình bao sẽ thực hiện. Shell chịu trách nhiệm chuyển đổi dòng bạn nhập vào trình bao thành các thẻ, sau đó được chuyển đến sys.argv, một mảng python/chuỗi các đối số dòng lệnh. Mô-đun argparse chỉ đơn giản là làm cho cảm giác về những gì xuất hiện trong sys.argv.

Sự khác biệt này sẽ làm rõ cả hai "lỗi" mà bạn nhận thấy. Trước tiên, hãy xem xét -w "-4.5.5-double_non-parallel_gcc" (lưu ý việc thiếu dấu bằng). Trình bao phân tích cú pháp hai mã này là -w-4.5.5-double_non-parallel_gcc và cả hai chuỗi này được chuyển tới sys.argv. Không có dấu bằng, đây dường như là hai tùy chọn: -w (không có đối số) và -4 với đối số .5.5-double_non-parallel_gcc.Bạn cần dấu bằng để mọi thứ được phân tách thành một mã thông báo duy nhất.

biên soạn phần

Đối với 2&>, nó là không thể đối với argparse để kiểm soát xem một token cung cấp được coi là một cuộc tranh cãi hay không. Nếu có gì đó xuất hiện trong sys.argv, điều đó có nghĩa là vỏ của bạn đang xử lý nó làm đối số.

Dấu hiệu thông báo ở đây là thông báo lỗi. Lưu ý rằng thư không phải là unrecognized arguments: 2&>, mà là, unrecognized arguments: 2. Vỏ của bạn nhận ra "&>" là chuyển hướng đầu ra và phân tích phần còn lại của dòng (bao gồm tệp nhật ký) cho phù hợp. Đối số duy nhất được chuyển là "2", bởi vì 2&> không phải là loại chuyển hướng thực. (&> đã bao gồm cả stderr và stdout, vì vậy những gì sẽ là 2 thêm vào nó?)

Trong một bình luận, bạn tuyên bố rằng optparse có thể "xử lý" các "2 &>". Đó không phải là trường hợp thực sự. Mô-đun optparse thực hiện chính xác những gì argparse thực hiện, nhưng optparse không xác thực đối số vị trí như argparse. Trong thực tế, optparse là để cho một lỗi lập trình thực sự (trong trường hợp này, sử dụng 2&> như là một loại chuyển hướng vỏ) trượt bằng không bị phát hiện! Bạn nên gửi mã optparse ban đầu của bạn, nhưng tôi nghi ngờ bạn phân tích lập luận của bạn như sau:

opt, args = parser.parse_args() 

Kịch bản của bạn không có đối số vị trí, vì vậy tôi tưởng tượng bạn đã làm không có gì khác với args sau đó. Nhưng nếu bạn kiểm tra args, bạn sẽ thấy rằng 2 được coi là một đối số vị trí!

Nói chung, nếu một kịch bản không có đối số vị trí và bạn sử dụng optparse, một thói quen tốt để xác minh rằng bạn nhận được không có đối số vị trí, như vậy:

opt, args = parser.parse_args() 
if args: 
    parser.error("script takes no positional arguments") 

Module argparse làm việc đó cho bạn , đó là những gì đặt nó dặm trước optparse (trong số những lý do khác).

+0

Mọi thứ đều hoạt động tốt với 'optparse'. Nhưng có vẻ như rằng '" -4.5.5-double_non-parallel_gcc "' là một "tên tùy chọn không hợp lệ", và trong khi 'optparse' để lại dấu ngoặc kép,' argparse' không - do đó là lỗi. Nhưng còn phần '2 &>' thì sao? Nó đã làm việc tốt với 'optparse'. Nó hoạt động tốt với không có 2: '&>'. Tôi có thể sống theo cách này - nhưng nó có lạ không? Nó cần được giải quyết. Nó cũng hoạt động với '2 &>'. – Adobe

+0

Tôi đã chỉnh sửa câu trả lời ở trên để giải quyết mối quan tâm của bạn. Một lần nữa, '2 &>' không phải là một lá cờ chuyển hướng thực sự; '2>' là, và '&>' là, và thậm chí '2> & 1', nhưng không phải' 2 &> '. Nếu bạn không tin tôi, hãy thử nó với một trình bao tích hợp sẵn: 'ls 2 &> tmp.txt'. Các '&>' bắt stderr, vì vậy bạn sẽ không nhìn thấy nó ngay lập tức, nhưng nếu bạn nhìn vào tmp.txt bạn sẽ thấy thông báo lỗi. – HardlyKnowEm

+0

Tôi chưa từng sử dụng 'args'. Vì vậy, bạn đã giải quyết tất cả! – Adobe

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