PyQt 的优雅命令行参数解析

2024-02-15

我正在编写一个新的 PyQt 应用程序。我正在尝试使用尽可能多的 PyQt API 来完成与程序和 ui 相关的所有事情,作为提高我对 PyQt 和 Qt 总体知识的一种手段。

我的问题是,PyQt/Qt 中是否有 API 可以优雅地处理命令行参数解析?

到目前为止我的研究表明:

  • 制作方法的示例与 python 的 opt_parser 配合得很好 http://lateral.netmanagers.com.ar/weblog/posts/BB997.html模块,但它不处理 QApplication 的内置 arg 解析。
  • PyKDE 的 KCmdLineArgs http://techbase.kde.org/Development/Languages/Python/Using_PyKDE_4#KCmdLineArgs.2C_KAboutData(这引入了不需要的 KDE 依赖项)
  • 看起来 KCmdLineArgs 正在作为 QCommandLineParser 移植到 Qt5.1 的上游,这很酷,但我希望现在就可以使用它,而不是 18 个月后。

那么 PyQt 应用程序通常如何处理这个问题呢?或者是 opt_parser/argparse 的出路?

这远不是一个好的解决方案......

#!/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)

这里最好的解决方案是使用argparse模块的parse_known_args()方法 (docs http://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.parse_known_args) 首先处理非 Qt 命令行选项。不再需要进行配置工作ArgumentParser—它只是更改您调用的方法,并在返回中为您提供一个元组而不是单个对象。这让您两全其美。

一个简化的示例,仅捕获几个 Qt 4.8 参数和其他一些参数,但给出了总体思路。

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

假设您要这样运行:

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

Then parsed_args会有平常的Namespace with holy_hand_grenade set to 3 and --swallow set to 'unladen', while unparsed_args会有一个简单的列表:['-dograb', '-style,' 'cde']。这又可以正常传递给QApplication包含程序名称sys.argv[0](谢谢marcin https://stackoverflow.com/users/104453/marcin for 指出这一点 https://stackoverflow.com/questions/11713006/elegant-command-line-argument-parsing-for-pyqt/21166631?noredirect=1#comment50925070_21166631)。我们用sys.argv[:1]获取一个用于连接的数组unparsed_args;你也可以这样做[sys.argv[0]]

除此之外,这还可以让您设置应用程序来指定是否启动 Qt UI、是否作为命令行运行、是否运行单元测试等等(如果您愿意的话)。首先处理非 Qt(或其他任何)参数会更好,因为它不会留下argparse取决于您正在使用的设置,但反之亦然。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PyQt 的优雅命令行参数解析 的相关文章

  • Flask中使用的路由装饰器是如何工作的

    我熟悉 Python 装饰器的基础知识 但是我不明白这个用于 Flask 路由的特定装饰器是如何工作的 以下是 Flask 网站上的代码片段 from flask import Flask escape request app Flask
  • LibreOffice 并行将 .docx 转换为 .pdf 效果不佳

    我有很多 docx 文件需要转换为 pdf 将它们一一转换需要很长时间 所以我编写了一个 python 脚本来并行转换它们 from subprocess import Popen import time import os os chdi
  • 如何使用 python 的 http.client 准确读取一个响应块?

    Using http client在 Python 3 3 或任何其他内置 python HTTP 客户端库 中 如何一次读取一个分块 HTTP 响应一个 HTTP 块 我正在扩展现有的测试装置 使用 python 编写 http clie
  • 如何在python中附加两个字节?

    说你有b x04 and b x00 你如何将它们组合起来b x0400 使用Python 3 gt gt gt a b x04 gt gt gt b b x00 gt gt gt a b b x04 x00
  • Python re无限执行

    我正在尝试执行这段代码 import re pattern r w w s re compiled re compile pattern results re compiled search COPRO HORIZON 2000 HOR p
  • 为什么第二个 request.session cookies 返回空?

    我想使用 requests Session post 登录网站 但是当我已经登录主页 然后进入帐户页面时 看来cookies还没有保存 因为cookies是空的 而且我无法进入正确的帐户页面 import requests from bs4
  • 在Python中读取tiff标签

    我正在尝试用 Python 读取 tiff 文件的标签 该文件是 RGB 的uint16每个通道的值 我目前正在使用tifffile import tifffile img tifffile imread file tif 然而 img是一
  • Python“非规范化”unicode 组合字符

    我正在寻找标准化 python 中的一些 unicode 文本 我想知道是否有一种简单的方法可以在 python 中获得组合 unicode 字符的 非规范化 形式 例如如果我有序列u o xaf i e latin small lette
  • 将字符串中的随机字符转换为大写

    我尝试随机附加文本字符串 这样就不只是有像这样的输出 gt gt gt david 我最终会得到类似的东西 gt gt gt DaViD gt gt gt dAviD 我现在的代码是这样的 import random import stri
  • Python守护进程:保持日志记录

    我有一个将一些数据记录到磁盘的脚本 logging basicConfig filename davis debug log level logging DEBUG logging basicConfig filename davis er
  • PyInstaller“ValueError:源代码字符串不能包含空字节”

    我得到了一个ValueError source code string cannot contain null bytes执行命令时pyinstaller main py在具有和不具有管理员权限的cmd中 Traceback most re
  • 在 numpy 中连接维度

    我有x 1 2 3 4 5 6 7 8 9 10 11 12 shape 2 2 3 I want 1 2 3 4 5 6 7 8 9 10 11 12 shape 2 6 也就是说 我想连接中间维度的所有项目 在这种特殊情况下我可以得到这
  • 非法指令:MacOS High Sierra 上有 4 条指令

    我正在尝试在 pygame 3 6 中制作一个看起来像聊天的窗口 我刚刚将我的 MacBook 更新到版本 10 13 6 在我这样做之前它工作得很好 但在我收到消息之后 非法指令 4 Code import pygame from pyg
  • 高效创建抗锯齿圆形蒙版

    我正在尝试创建抗锯齿 加权而不是布尔 圆形掩模 以制作用于卷积的圆形内核 radius 3 no of pixels to be 1 on either side of the center pixel shall be decimal a
  • 在matlab中,如何读取python pickle文件?

    在 python 中 我生成了一个 p 数据文件 pickle dump allData open myallData p wb 现在我想在Matlab中读取myallData p 我的Matlab安装在Windows 8下 其中没有Pyt
  • 如何绘制更大的边界框和仅裁剪边界框文本 Python Opencv

    我正在使用 easyocr 来检测图像中的文本 该方法给出输出边界框 输入图像如下所示 Image 1 Image 2 使用下面的代码获得输出图像 But I want to draw a Single Bigger bounding bo
  • 如何在 scikit 中加载 CSV 数据并将其用于朴素贝叶斯分类

    尝试加载自定义数据以在 Scikit 中执行 NB 分类 需要帮助将示例数据加载到 Scikit 中 然后执行 NB 如何加载目标的分类值 使用相同的数据进行训练和测试 或使用完整的数据集进行测试 Sl No Member ID Membe
  • Jupyter Notebook:带有小部件的交互式绘图

    我正在尝试生成一个依赖于小部件的交互式绘图 我遇到的问题是 当我使用滑块更改参数时 会在前一个绘图之后完成一个新绘图 而我预计只有一个绘图会根据参数发生变化 Example from ipywidgets import interact i
  • 如何使用xlwt设置文本颜色

    我无法找到有关如何设置文本颜色的文档 在 xlwt 中如何完成以下操作 style xlwt XFStyle bold font xlwt Font font bold True style font font background col
  • Python 中的 Unix cat 函数 (cat * > merged.txt)? [复制]

    这个问题在这里已经有答案了 一旦建立了目录 有没有办法在Python中使用Unix中的cat函数或类似的函数 我想将 files 1 3 合并到 merged txt 我通常会在 Unix 中找到该目录 然后运行 cat gt merged

随机推荐