繁体   English   中英

将 python 队列模块从 python2 转换为 python3

[英]converting the python queue module from python2 to python3

我有一个日志记录脚本,它将串行项队列中多个设备的串行输出记录到标准输出中。 在 python 2.7 中,脚本按预期工作。 但是,将脚本转换为 python3. 我注意到,在将队列模块转换为它的 python3 形式后,我的脚本开始打印除了常规预期输出之外的空行。 有人可以解释这是什么原因以及解决此问题的任何最佳做法吗?

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import serial
import sys
import threading
from datetime import datetime
import glob
import time
import os
import termcolor as tc
import queue

__version__ = 2.0

COLOR = True
# Available colors
#   blue, yellow, green, cyan,
#   magenta, white, red, grey,
#   light_grey, on_red

# Add light grey to the colors dictionary
tc.COLORS['light_grey'] = 38
# Add a highlight color
tc.COLORS['on_red'] = 41

TIMEOUT = 0.05 # seconds

DEVS = []
usb_devices = []
speaker_types = ['Tx', 'Rx-FL', 'Rx-FR', 'Rx-Center', 'Rx-Subwoofer']

stamp = time.strftime("%Y:%m:%d-%H:%M:%S")

def serial_ports():
    if sys.platform.startswith('win'):
        ports = ['COM%s' % (i + 1) for i in range(256)]
    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
        ports = glob.glob('/dev/tty[A-Za-z]*')
    elif sys.platform.startswith('darwin'):
        ports = glob.glob('/dev/tty.*')
    else:
        raise EnvironmentError('Unsupported platform')
    result = []
    for port in ports:
        try:
            s = serial.Serial(port)
            s.close()
            result.append(port)
        except (OSError, serial.SerialException):
            pass
    result.reverse()
    print("Ports: " + str(result))
    pattern = 'USB'
    usb_devices = [string for string in result if pattern in string]
    return usb_devices
    
def add_device(position):    
    name = speaker_types[position]
    return name


class SerialTerm(object):
    """A serial terminal that runs in its own thread"""
    def __init__(self, name, port, timeout, queue, baudrate=2000000, color=None):
        self.name = name
        self.port = port
        self.timeout = timeout
        self.queue = queue
        self.baudrate = baudrate
        self.color = color

        self.receiver_thread = None
        self.alive = None

        self.serial = serial.serial_for_url(
            self.port,
            timeout=self.timeout,
            baudrate=self.baudrate)

    def start(self):
        """Starts the terminal thread"""
        self.alive = True
        self.receiver_thread = threading.Thread(target=self.reader)
        self.receiver_thread.setDaemon(True)
        self.receiver_thread.start()
        #self.reset()

    def stop(self):
        """Stops the terminal thread"""
        self.alive = False
        self.receiver_thread.join()

    def reader(self):
        """Reads data from the associated serial port and puts the data in a
        queue"""
        while self.alive:
            now = datetime.utcnow()
            line = self.serial.readline()
            if line != "": 
                output_str = f"{now.time().isoformat()[:12]}(UTC) {self.name}> {line}"

                if COLOR and (self.color is not None):
                    output_str = tc.colored(output_str, self.color)
                    
                self.queue.put(output_str)


    def join(self):
        """Waits until thread terminates"""
        self.receiver_thread.join()
        
def main():
    print("Getting Devices")
    dev = serial_ports()
    
    position = 0
    name = ''

    for d in dev:
        name = add_device(position)
        DEVS.append({'port':dev[position], 'name':name, 'color':'white'})
        position += 1
        
    print('DEVS: ' + str(DEVS))
    
    """Round robin serial polling"""
    sys.stdout.write("v{}\n".format(__version__))
    sys.stdout.flush()
    que = queue.Queue()

    terms = []
    for dev in DEVS:
        terms.append(
            SerialTerm(
                name=dev['name'],
                port=dev['port'],
                color=dev['color'],
                timeout=TIMEOUT,
                queue=que))

    for term in terms:
        term.start()

    try:
        while True:
            try:
                # The queue.get method needs a timeout or KeyboardInterrupt won't ever raise.
                sys.stdout.write(que.get(timeout=60) + "\n")
                sys.stdout.flush()
            except queue.Empty: 
                pass
    except KeyboardInterrupt:
        sys.stderr.write("\nQuitting\n")
        for term in terms:
           term.stop()
           term.join()
           sys.exit()
           sys.stdout.flush()
    except:
        raise

if __name__ == '__main__':
    main()

这是 python3 给我的错误输出示例。 除了显示的任何正常打印输出之外,它只会无限期地向这些空行发送垃圾邮件。

00:53:00.859(UTC) Tx> b''
00:53:00.909(UTC) Tx> b''
00:53:00.960(UTC) Tx> b''
00:53:01.010(UTC) Tx> b''
00:53:01.061(UTC) Tx> b''
00:53:01.111(UTC) Tx> b''
00:53:00.859(UTC) Tx> b'Expected Printout'
00:53:00.909(UTC) Tx> b''
00:53:00.960(UTC) Tx> b''
00:53:01.010(UTC) Tx> b''
00:53:01.061(UTC) Tx> b''
00:53:01.111(UTC) Tx> b''

错误在这里:

            line = self.serial.readline()
            if line != "": 
                output_str = f"{now.time().isoformat()[:12]}(UTC) {self.name}> {line}"

                if COLOR and (self.color is not None):
                    output_str = tc.colored(output_str, self.color)
                    
                self.queue.put(output_str)

self.serial.readline()返回一个bytes对象。 结果,它不会比较等于str对象,例如"" ,因此不再过滤掉空行。

要修复它,您需要使用bytes.decodeself.serial.readline()的返回值转换为str

有关在 python 3 中对字符串所做的更改以及如何正确移植 python 2 代码的更多详细信息, 请参阅本指南

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM