【问题标题】:In Pyside: QProcess.write(u'Test') returns 0L在 Pyside: QProcess.write(u'Test') 返回 0L
【发布时间】:2014-11-10 00:20:08
【问题描述】:

我的理解是在 Pyside QString 已被删除。可以将 Python 字符串写入 QLineEdit,当读取 QLineEdit 时,它会作为 unicode 字符串(每个字符 16 位)返回。

尝试将此字符串从我的 Gui 进程写入使用 QProcess 启动的子进程似乎不起作用,只会返回 0L(见下文)。如果使用str() 函数将Unicode 字符串改回Python 字符串,那么self.my_process.write(str(u'test')) 现在返回4L。这种行为对我来说似乎不正确。

有人可以解释为什么QProcess.write() 似乎不适用于 unicode 字符串吗?

(Pdb) PySide.QtCore.QString()
*** AttributeError: 'module' object has no attribute 'QString'
(Pdb) self.myprocess.write(u'test')
0L
(Pdb) self.myprocess.write(str(u'test'))
4L
(Pdb) 

【问题讨论】:

    标签: python string unicode pyside qprocess


    【解决方案1】:

    PySide 从未提供过像 QString、QStringList、QVariant 等这样的类。它总是对等价的 python 类型进行隐式转换——也就是说,在 PyQt 术语中,它只实现了v2 API(参见PSEP 101了解更多详情)。

    然而,与 PyQt4 相比,QProcess 在尝试编写 unicode 字符串时的行为在 PySide 中似乎有些问题。这是 PyQt4 中的一个简单测试:

    Python 2.7.8 (default, Sep 24 2014, 18:26:21) 
    [GCC 4.9.1 20140903 (prerelease)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from PyQt4 import QtCore
    >>> QtCore.PYQT_VERSION_STR
    '4.11.2'
    >>> p = QtCore.QProcess()
    >>> p.start('cat'); p.waitForStarted()
    True
    >>> p.write(u'fóó'); p.waitForReadyRead()
    3L
    True
    >>> p.readAll()
    PyQt4.QtCore.QByteArray('f\xf3\xf3')
    

    因此,PyQt 似乎会将 unicode 字符串隐式编码为“latin-1”,然后再将它们传递给QProcess.write()(当然需要const char *QByteArray)。如果您想要不同的编码,则必须明确完成:

    >>> p.write(u'fóó'.encode('utf-8')); p.waitForReadyRead()
    5L
    True
    >>> p.readAll()
    PyQt4.QtCore.QByteArray('f\xc3\xb3\xc3\xb3')
    

    现在让我们看看 PySide 会发生什么:

    Python 2.7.8 (default, Sep 24 2014, 18:26:21) 
    [GCC 4.9.1 20140903 (prerelease)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from PySide import QtCore, __version__
    >>> __version__
    '1.2.2'
    >>> p = QtCore.QProcess()
    >>> p.start('cat'); p.waitForStarted()
    True
    >>> p.write(u'fóó'); p.waitForReadyRead()
    0L
    ^C
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyboardInterrupt
    

    所以:没有隐式编码,进程只是阻塞而不是引发错误(这似乎是一个错误)。但是,使用显式编码重新尝试按预期工作:

    >>> p.start('cat'); p.waitForStarted()
    True
    >>> p.write(u'fóó'.encode('utf-8')); p.waitForReadyRead()
    5L
    True
    >>> p.readAll()
    PySide.QtCore.QByteArray('fóó')
    

    【讨论】:

    • 谢谢;很好的解释;由于 Pyside 中 Qt 中的几乎所有内容都是 unicode,我原以为 QProcess.write() 可以处理 unicode 字符串,而无需编码为不同的格式;我想我同意你的评论,即使用 QProcess 时 Pyside 似乎坏了。目前,我还没有弄清楚当它是 Python 时如何将调试器附加到子进程;这将有助于理解 QProcess 何时阻塞。我想知道 dbus-python 是否会是进程之间通信的更好方式?
    • @bit_pusher。在某些时候,unicode 对象在写入之前总是必须编码为字节;没有办法直接写出来。唯一的问题是编码是否是隐式完成的。就个人而言,我总是会避免这种情况,并通过自己设置来确保使用正确的编码。显式优于隐式(尤其是在编码方面)。
    • 我不太明白为什么 unicode 不能直接写入,因为我的理解是“编码为字节”。我的理解是大多数 unix 和 Python 使用 UTF-8 unicode,它确实指定了大多数语言的每个字符的字节是什么,如果这是真的,应该发送这些 UTF-8 字节。我还认为可以相当可靠地检测到 UTF-8?失败的操作不应该(在这种情况下 QProcess.write() 给出一些反馈吗?我怀疑 QProcess 正在使用文本流而不是二进制流;有人可以指导我查看有关这些问题的文档吗?
    • 好吧,正如我所说,你重复了,unicode 不能直接写入,因为它必须先编码为字节。 Unicode 对象本身没有编码;他们只是将代码点映射到字符。为了将 unicode 从一个地方传输到另一个地方,它必须以标准格式编码,并以字节的形式发送(UTF == Unicode 转换格式)。最大的问题始终是:应该使用哪种编码?如果你自己不决定这个,你就是在强迫 Python 去猜测,并且无法保证它总是能猜对。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 1970-01-01
    相关资源
    最近更新 更多