2012-07-29 31 views
8

Tôi đang viết một ứng dụng PyQt mới. Tôi đang cố gắng làm tất cả mọi thứ liên quan đến chương trình và ui sử dụng càng nhiều các API PyQt càng tốt như một phương tiện để cải thiện kiến ​​thức của tôi về PyQt và Qt nói chung.Phân tích đối số dòng lệnh thanh lịch cho PyQt

Câu hỏi tôi có là, có API trong PyQt/Qt để xử lý đối số dòng lệnh phân tích cú pháp một cách thanh lịch không?

Nghiên cứu của tôi cho đến nay đã bật lên:

  • một ví dụ về làm thế nào để làm cho nó play nice with python's opt_parser mô-đun, ngoại trừ nó không xử lý QApplication được xây dựng trong arg phân tích cú pháp.
  • PyKDE's KCmdLineArgs (trong đó giới thiệu một không mong muốn KDE phụ thuộc)
  • nó trông giống như KCmdLineArgs đang được chuyển ngược dòng cho Qt5.1 như QCommandLineParser, đó là mát mẻ, nhưng tôi muốn để có thể sử dụng nó bây giờ, không 18 tháng từ giờ.

Vậy các ứng dụng PyQt thường xử lý việc này như thế nào? hoặc là opt_parser/argparse con đường để đi?

Đây là xa một giải pháp tốt đẹp ...

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import sys, argparse 
from PyQt4 import QtGui 

def main(argv): 

    app = QtGui.QApplication(argv) # QApplication eats argv in constructor 

    # We can get a QStringList out of QApplication of those arguments it 
    # didn't decide were reserved by Qt. 
    argv2 = app.arguments() 

    # now we need to turn them back into something that optparse/argparse 
    # can understand, since a QStringList is not what it wants 
    argv3 = [] 
    for i in argv2: 
    argv3.append(str(i)) 

    # now we can pass this to optparse/argparse 
    process_args(argv3) 

    # dummy app 
    mw = QtGui.QMainWindow() 
    mw.show() 
    sys.exit(app.exec_()) 

def process_args(argv): 
    parser = argparse.ArgumentParser(description='PyQt4 argstest', 
            add_help=False) 

    # we now have to add all of the options described at 
    # http://qt-project.org/doc/qt-4.8/qapplication.html#QApplication 
    # but have them do nothing - in order to have them show up in the help list 

    # add this to the list if Qt is a debug build (How to detect this?) 
    parser.add_argument("-nograb", action=ignore, 
         help="don't grab keyboard/mouse for debugging") 

    # add these to the list if Qt is a debug build for X11 
    parser.add_argument("-dograb", action=ignore, 
         help="grab keyboard/mouse for debugging") 
    parser.add_argument("-sync", action=ignore, 
         help="run in synchronous mode for debugging") 

    # add all the standard args that Qt will grab on all platforms 
    parser.add_argument("-reverse", action=ignore, 
         help="run program in Right-to-Left mode") 
    # an example -- there are 10 such items in the docs for QApplication 

    # then we need to figure out if we're running on X11 and add these 
    parser.add_argument("-name", action=ignore, 
         help="sets the application name") 
    # an example -- there are 13 such items in the docs 

    # reimplement help (which we disabled above) so that -help works rather 
    # than --help; done to be consistent with the style of args Qt wants 
    parser.add_argument("-h", "-help", action='help', 
         help="show this help message and exit") 

    parser.parse_args(argv[1:]) 

class ignore(argparse.Action): 
    # we create an action that does nothing, so the Qt args do nothing 
    def __call__(self, parser, namespace, values, option_string=None): 
    pass 

if __name__ == "__main__": 
    main(sys.argv) 
+2

Toàn bộ điểm của bài đăng của tôi tại lateral.netmanagers.com.ar mà bạn đã đề cập là nó xử lý phân tích cú pháp dòng lệnh dựng sẵn của QApplication. Bạn xác định các đối số của riêng bạn bằng cách sử dụng opt_parse/argparse/bất cứ điều gì, và miễn là bạn không xác định những cái mà QApplication sử dụng, mọi thứ chỉ hoạt động. –

Trả lời

3

Sử dụng argparse nếu bạn đang sử dụng Python 2.7 (optparse nếu < 2.7), gói không nhất thiết phải được cụ thể cho PyQt cho bạn xử lý các tùy chọn dòng lệnh.

+2

+1 vì không có lý do để cần pyqt cung cấp cơ sở khi python stdlib có một mô-đun đầy đủ tính năng pefectly. – jdi

+2

Được rồi, tôi đọc lên trên argparse và nó có vẻ tốt đẹp, tuy nhiên nó không giải quyết các vấn đề chơi tốt đẹp với QApplication được xây dựng trong phân tích cú pháp arg. Ví dụ: nếu bạn chạy 'myPyQyApp.py-style cde' từ dòng lệnh, QApplication chặn đối số đó và làm mọi thứ trông giống như năm 1996, nhưng argparse không có ý tưởng điều này đang xảy ra. Đó là lý do tại sao tôi đang tìm kiếm một giải pháp PyQt. Nếu không tồn tại, thì cũng vậy, nhưng giải pháp stdlib không phải là tối ưu. –

+2

Nếu bạn không muốn Qt phân tích cú pháp dòng lệnh, chỉ cần tạo ứng dụng như sau: 'app = QtGui.QApplication ([])' – pwuertz

5

Giải pháp tốt nhất ở đây là sử dụng phương pháp của mô-đun parse_known_args() (docs) để xử lý các tùy chọn dòng lệnh không phải Qt trước. Nó không hoạt động nhiều trong việc cấu hình ArgumentParser — chỉ thay đổi phương thức bạn gọi và cung cấp cho bạn một bộ dữ liệu thay vì một đối tượng duy nhất trong phần trả về. Điều đó mang lại cho bạn tốt nhất của cả hai thế giới.

Ví dụ đơn giản chỉ bắt được một vài đối số Qt 4.8 và một số khác, nhưng đưa ra ý tưởng chung.

# my_script.py 

import argparse 
from PyQt4 import QtGui # this will work with PySide.QtGui, too 

def process_cl_args(): 
    parser = argparse.ArgumentParser() 
    parser.add_argument('-s', '--swallow', action='store') # optional flag 
    parser.add_argument('holy_hand_grenade', action='store') # positional argument 

    parsed_args, unparsed_args = parser.parse_known_args() 
    return parsed_args, unparsed_args 

if __name__ == '__main__': 
    parsed_args, unparsed_args = process_cl_args() 
    # QApplication expects the first argument to be the program name. 
    qt_args = sys.argv[:1] + unparsed_args 
    app = QtGui.QApplication(qt_args) 
    # ... the rest of your handling: `sys.exit(app.exec_())`, etc. 

Giả sử bạn đang chạy này như sau:

$ python my_script.py -dograb --swallow=unladen 3 -style cde 

Sau đó parsed_args sẽ có thông thường Namespace với holy_hand_grenade thiết lập để 3--swallow thiết lập để 'unladen', trong khi unparsed_args sẽ có một danh sách đơn giản: ['-dograb', '-style,' 'cde'] . Điều này lần lượt có thể được chuyển bình thường đến QApplication với việc bao gồm tên chương trình từ sys.argv[0] (nhờ marcin cho pointing this out). Chúng tôi sử dụng sys.argv[:1] để có được một mảng cho nối với unparsed_args; bạn cũng có thể làm [sys.argv[0]]

Trong số những thứ khác, điều này cho phép bạn thiết lập ứng dụng của mình để chỉ định có khởi chạy giao diện Qt hay không, để chạy dưới dạng dòng lệnh, để chạy thử nghiệm đơn vị, v.v. mong muốn. Việc xử lý các đối số không phải Qt (hoặc bất kỳ điều gì khác) trước tiên là tốt hơn bởi vì nó không để lại argparse phụ thuộc vào thiết lập bạn đang sử dụng, nhưng ngược lại.

+0

Điều gì sẽ xảy ra nếu tôi muốn ứng dụng qt có quyền truy cập vào args được phân tích cú pháp? – qed

+0

@qed, trong trường hợp đó, bạn chỉ có thể chuyển 'sys.argv' trực tiếp thay vì' unparsed_args'. –

+0

Nhưng tôi có thể sử dụng argparse bên trong QApplication không? – qed

0

Bạn thực sự nên thử docopt. Nó không cần bất kỳ định nghĩa đối số nào.Bạn có chuỗi "Sử dụng:" và các đối số chưa được phân tích làm đầu vào, chuyển chúng vào hàm docopt() và bạn đã phân tích cú pháp đối số làm đầu ra.

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