Piszę nową aplikację Pyqt. Próbuję zrobić wszystko związane z programem i UI, używając jak największej ilości API Pyqt, jak to możliwe, jako środek do poprawy mojej znajomości Pyqt i QT w ogóle.

Pytanie, które mam, czy istnieje API w Pyqt / QT, aby obsługiwać argument wiersza poleceń.

Dotychczas moje badania:

  • Przykład tego, jak to zrobić Play Nicea z modułem Pythona OPT_PARSER, z wyjątkiem tego, że nie obsługuje Kapplikacje zbudowane w anglice.
  • Pykde's Kcmdlineargs (co wprowadza niepożądaną zależność KDE)
  • Wygląda na to, że Kcmdlineargs jest przenoszony do QT5.1 jako QCommandlineParser, który jest fajny, ale chciałbym być w stanie go teraz używać, nie 18 miesięcy od teraz.

Jak więc aplikacje PYQT normalnie to obsługują? czy jest opt_parser / argparat ma sposób, aby iść?

Jest to daleko od ładnego rozwiązania ...

#!/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)
12
troy.unrau 30 lipiec 2012, 01:13

3 odpowiedzi

Najlepsza odpowiedź

Użyj argparat jeśli używasz Python 2.7 (Optparse IF & LT; 2.7), pakiet nie musi być specyficzny Pyqt, aby obsługiwać opcje poleceń.

4
aayoubi 29 lipiec 2012, 21:51

Najlepszym rozwiązaniem jest użycie metody modułu {x0}} {X0}} (Dokumenty), aby najpierw przetworzyć opcje wiersza poleceń innych niż QT. Nie ma więcej pracy w konfigurowaniu ArgumentParser - po prostu zmienia się, która metoda nazywasz i zapewnia krotkę zamiast pojedynczego obiektu w powrocie. To daje najlepsze z obu światów.

Uproszczony przykład, który łapie tylko kilka argumentów QT 4.8 i kilku innych, ale daje ogólnemu pomysłowi.

# 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.

Załóżmy, że to zrobiłeś tak:

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

Następnie parsed_args miałby zwykłe Namespace z holy_hand_grenade ustawioną na 3 i --swallow ustawiony na 'unladen', podczas gdy unparsed_args miałaby Prosta lista: ['-dograb', '-style,' 'cde']. To z kolei można przekazać normalnie do QApplication z włączeniem nazwy programu z sys.argv[0] (dzięki Marcin dla wskazując to). Używamy sys.argv[:1], aby uzyskać tablicę do konkatenacji z unparsed_args; mógłbyś równie dobrze zrobić {{x12}}

Między innymi pozwala to skonfigurować aplikację, aby określić, czy uruchomić identyfikator QT UI, aby uruchomić jako wiersz polecenia, uruchomić testy jednostkowe i tak dalej, jeśli tak pożądane. Obsługa argumentów innych niż qt (lub cokolwiek innego), najpierw jest lepsze, ponieważ nie pozostawia argparse zależy od konfiguracji, której używasz, ale na odwrót.

9
Community 23 maj 2017, 11:44

Powinieneś naprawdę spróbować Docopt. Nie potrzebuje żadnych definicji argumentów. Masz "użycie:" ciąg i nieobsługiwane argumenty jako wejście, przekazać je w funkcji Docopt (), a przewidywano argumenty jako wyjście.

0
Alexander Shishenko 5 styczeń 2016, 20:49