当从 Python 2 移植到 Python 3

问题描述

所以碰巧我正在编写一个应用程序和一个 Chrome 扩展程序。因此,我设置了 Native Messaging 以允许彼此交谈,我得到了一种状态,在遵循文档甚至一些教程的情况下,我可以在使用 Python 2.7 的同时使扩展端工作和主机工作,尽管当我尝试将相同的主机脚本移植到 Python 3,这是我的程序的其余部分编写的实际语言,再次遵循文档、示例甚至解压缩 pypi 包的代码片段来这样做,现在我无法让它正常工作,它相应地发送消息,但无法接收它们。请注意事情的扩展方面没有改变,AFAIK 不应该改变。

作为参考,我使用的最好的资源之一是 https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging,它确实有 Python 3 兼容性部分和 https://developer.chrome.com/docs/apps/nativeMessaging/,Chrome 应用文档,但具有相同的扩展 API。

Python 2 代码

import struct
import sys
import os

# On Windows,the default I/O mode is O_TEXT. Set this to O_BINARY
# to avoid unwanted modifications of the input/output streams.
if sys.platform == "win32":
  import msvcrt
  msvcrt.setmode(sys.stdin.fileno(),os.O_BINARY)
  msvcrt.setmode(sys.stdout.fileno(),os.O_BINARY)

# Thread that reads messages from the webapp.
def read_thread_func():
  while True:
    # Read the message length (first 4 bytes).
    text_length_bytes = sys.stdin.read(4)
         
    if not text_length_bytes:
      sys.exit(0)
    
    # Unpack message length as 4 byte integer.
    text_length = struct.unpack('=I',text_length_bytes)[0]
    # Read the text (JSON object) of the message.
    text = sys.stdin.read(text_length).encode("utf-8")
      
    if (os.path.exists('./data')):
      with open('./data','wb') as f:
        f.write(text)
        f.close()
    else:
      with open('./data','xb') as f:
        f.write(text)
        f.close()

# Helper function that sends a message to the webapp.
def send_message(message):
  # Write message size.
  sys.stdout.write(struct.pack('=I',len(message.encode("utf-8"))))
  
  # Write the message itself.
  sys.stdout.write(struct.pack(str(len(message.encode("utf-8")))+"s",message.encode("utf-8")))
  sys.stdout.flush()

def index():
  send_message('{"msg": "Hello World!"}')
  read_thread_func()

if __name__ == '__main__':
  index()

以上代码完美运行

Python 3

...
def send_message(message):
  # Write message size.
  sys.stdout.buffer.write(struct.pack('=I',len(message.encode("utf-8"))))
  
  # Write the message itself.
  sys.stdout.buffer.write(struct.pack(str(len(message.encode("utf-8")))+"s",message.encode("utf-8")))
  sys.stdout.flush()
...

上面我只放了实际修改的代码,其余保持不变,但理论上这应该可以工作,尽管它没有,而且要清楚这个修改的部分只是负责发送消息的功能,即使在 Python 3 中它可以做,问题是阅读,我尝试了很多东西,包括只是复制出 Mozilla 代码片段,但似乎没有任何解决问题的方法,因为扩展端可能是正确的,因为它是注册表上的配置和各自的清单,因为在 Python 2 版本中它确实有效,我似乎无法找到问题,如果有人可以帮助我,我将不胜感激,感谢您的时间。

错误日志(不是真正的错误日志,而是我中断程序时出现的唯一内容):

Traceback (most recent call last):
  File "C:\path\to\handler",line 69,in <module>
    index()
  File "C:\path\to\handler",line 65,in index
    read_thread_func()
  File "C:\path\to\handler",line 17,in read_thread_func
    text_length_bytes = sys.stdin.read(4)
KeyboardInterrupt

否则它只显示一个符号(能够在控制台上显示的消息的 utf-8 解码长度,以及立即发送的实际消息,这适用于这两种情况并且是预期的,因为使用标准输入发送消息 AFAIK)

对于 Python 3: ".\python3.9\python.exe" "处理程序" 对于 Python 2:

".\python27\python.exe" "handler"

这是启动程序的命令行,注意前面提到的文件的文件名是处理程序,也尝试使用 -u 选项启动它,就像我在 Windows 10 中一样。Python 模块 2to3.py 也没有发现任何要移植的东西。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)