pyserial serialwin32.py has attribute error

﹥>﹥吖頭↗ 提交于 2019-12-01 12:26:53

问题


I'm new to Python and trying to run a demo provide by Invensense. They provide a Python client which should take COM traffic and manipulate a graphic. The demo seems to crash out of the box and I'm not sure if I have something wrong with pyserial that I installed. The requirements were python2.7, pyserial and pygame. The pyserial executable serialwin32.py throws this error:

Traceback (most recent call last):
.......
  File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 47, in open
if port.upper().startswith('COM') and int(port[3:]) > 8:
AttributeError: 'int' object has no attribute 'upper'

Using input from user 101 (not sure how to thank you in the system - but THANKS!)

port = str(self.name)

This error is resolved. However as is always the case the next error presents a couple of lines farther down when windows seems to deny access:

 File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 66, in open
raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))

serial.serialutil.SerialException: could not open port 'COM6': WindowsError(5, 'Access is denied.')

The partial code reference seems to be:

self.hComPort = win32.CreateFile(port,
           win32.GENERIC_READ | win32.GENERIC_WRITE,
           0, # exclusive access
           None, # no security
           win32.OPEN_EXISTING,
           win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
           0)
    if self.hComPort == win32.INVALID_HANDLE_VALUE:
        self.hComPort = None    # 'cause __del__ is called anyway
        raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))

Full Code excerpt at end.

Questions:
1) Any ideas how to get past this error?

2) My speculation :-( is that this may be a privileges issue but being new to python I'm not sure how to address if Windows 10 thinks it's protecting me...

3) I agree that I shouldn't have to modify pyserial at all (lots of people have likely tried it) so I suspect some other problem. However, I'm clueless so I'm posting the client python code here too.

---------- client application which requires pyserial,pygame ----------

#!/usr/bin/python
# eMPL_client.py

# A PC application for use with Embedded MotionApps.
# Copyright 2012 InvenSense, Inc. All Rights Reserved.
import serial, sys, time, string, pygame from ponycube import *

class eMPL_packet_reader:

def __init__(self, port, quat_delegate=None, debug_delegate=None, data_delegate=None ):

    self.s = serial.Serial(port,115200)

    self.s.setTimeout(0.1)

    self.s.setWriteTimeout(0.2)

# TODO: Will this break anything?

        ##Client attempts to write to eMPL.

        #try:

        #self.s.write("\n")

        #except serial.serialutil.SerialTimeoutException:

        #pass # write will timeout if umpl app is already started.



    if quat_delegate:

        self.quat_delegate = quat_delegate

    else:

        self.quat_delegate = empty_packet_delegate()



    if debug_delegate:

        self.debug_delegate = debug_delegate

    else:

        self.debug_delegate = empty_packet_delegate()



    if data_delegate:

        self.data_delegate = data_delegate

    else:

        self.data_delegate = empty_packet_delegate()



    self.packets = []

    self.length = 0

    self.previous = None



def read(self):

    NUM_BYTES = 23

    p = None

    while self.s.inWaiting() >= NUM_BYTES:

        rs = self.s.read(NUM_BYTES)

        if ord(rs[0]) == ord('$'):

            pkt_code = ord(rs[1])

            if pkt_code == 1:

                d = debug_packet(rs)

                self.debug_delegate.dispatch(d)

            elif pkt_code == 2:

                p = quat_packet(rs)

                self.quat_delegate.dispatch(p) 

            elif pkt_code == 3:

                d = data_packet(rs)

                self.data_delegate.dispatch(d)

            else:

                print "no handler for pkt_code",pkt_code

        else:

            c = ' '

            print "serial misaligned!"

            while not ord(c) == ord('$'):

                c = self.s.read(1)

            self.s.read(NUM_BYTES-1)

def write(self,a):

    self.s.write(a)

def close(self):

    self.s.close()

def write_log(self,fname):

    f = open(fname,'w')

    for p in self.packets:

        f.write(p.logfile_line())

    f.close()

# ===========  PACKET DELEGATES  ==========

class packet_delegate(object):

def loop(self,event):

    print "generic packet_delegate loop w/event",event

def dispatch(self,p):

    print "generic packet_delegate dispatched",p

class empty_packet_delegate(packet_delegate):

def loop(self,event):

    pass

def dispatch(self,p):

    pass



class cube_packet_viewer (packet_delegate):

def __init__(self):

    self.screen = Screen(480,400,scale=1.5)

    self.cube = Cube(30,60,10)

    self.q = Quaternion(1,0,0,0)

    self.previous = None  # previous quaternion

    self.latest = None    # latest packet (get in dispatch, use in loop)



def loop(self,event):

    packet = self.latest

    if packet:

        q = packet.to_q().normalized()

        self.cube.erase(self.screen)

        self.cube.draw(self.screen,q)

        pygame.display.flip()

        self.latest = None



def dispatch(self,p):

    if isinstance(p,quat_packet):

        self.latest = p

class debug_packet_viewer (packet_delegate):

def loop(self,event):

    pass

def dispatch(self,p):

    assert isinstance(p,debug_packet);

    p.display()

class data_packet_viewer (packet_delegate):

def loop(self,event):

    pass

def dispatch(self,p):

    assert isinstance(p,data_packet);

    p.display()



# =============== PACKETS ================= 


# For 16-bit signed integers.

def two_bytes(d1,d2):

d = ord(d1)*256 + ord(d2)

if d > 32767:

    d -= 65536

return d



# For 32-bit signed integers.

def four_bytes(d1, d2, d3, d4):

d = ord(d1)*(1<<24) + ord(d2)*(1<<16) + ord(d3)*(1<<8) + ord(d4)

if d > 2147483648:

    d-= 4294967296

return d


class debug_packet (object):

# body of packet is a debug string

def __init__(self,l):

    sss = []

    for c in l[3:21]:

        if ord(c) != 0:

            sss.append(c)

    self.s = "".join(sss)



def display(self):

    sys.stdout.write(self.s)



class data_packet (object):

def __init__(self, l):

    self.data = [0,0,0,0,0,0,0,0,0]

    self.type = ord(l[2])

    if self.type == 0:   # accel

        self.data[0] = four_bytes(l[3],l[4],l[5],l[6]) * 1.0 / (1<<16)

        self.data[1] = four_bytes(l[7],l[8],l[9],l[10]) * 1.0 / (1<<16)

        self.data[2] = four_bytes(l[11],l[12],l[13],l[14]) * 1.0 / (1<<16)

    elif self.type == 1:   # gyro

        self.data[0] = four_bytes(l[3],l[4],l[5],l[6]) * 1.0 / (1<<16)

        self.data[1] = four_bytes(l[7],l[8],l[9],l[10]) * 1.0 / (1<<16)

        self.data[2] = four_bytes(l[11],l[12],l[13],l[14]) * 1.0 / (1<<16)

    elif self.type == 2:   # compass

        self.data[0] = four_bytes(l[3],l[4],l[5],l[6]) * 1.0 / (1<<16)

        self.data[1] = four_bytes(l[7],l[8],l[9],l[10]) * 1.0 / (1<<16)

        self.data[2] = four_bytes(l[11],l[12],l[13],l[14]) * 1.0 / (1<<16)

    elif self.type == 3:   # quat

        self.data[0] = four_bytes(l[3],l[4],l[5],l[6]) * 1.0 / (1<<30)

        self.data[1] = four_bytes(l[7],l[8],l[9],l[10]) * 1.0 / (1<<30)

        self.data[2] = four_bytes(l[11],l[12],l[13],l[14]) * 1.0 / (1<<30)

        self.data[3] = four_bytes(l[15],l[16],l[17],l[18]) * 1.0 / (1<<30)

    elif self.type == 4:   # euler

        self.data[0] = four_bytes(l[3],l[4],l[5],l[6]) * 1.0 / (1<<16)

        self.data[1] = four_bytes(l[7],l[8],l[9],l[10]) * 1.0 / (1<<16)

        self.data[2] = four_bytes(l[11],l[12],l[13],l[14]) * 1.0 / (1<<16)

    elif self.type == 5:   # rot

        self.data[0] = two_bytes(l[3],l[4]) * 1.0 / (1<<14)

        self.data[1] = two_bytes(l[5],l[6]) * 1.0 / (1<<14)

        self.data[2] = two_bytes(l[7],l[8]) * 1.0 / (1<<14)

        self.data[3] = two_bytes(l[9],l[10]) * 1.0 / (1<<14)

        self.data[4] = two_bytes(l[11],l[12]) * 1.0 / (1<<14)

        self.data[5] = two_bytes(l[13],l[14]) * 1.0 / (1<<14)

        self.data[6] = two_bytes(l[15],l[16]) * 1.0 / (1<<14)

        self.data[7] = two_bytes(l[17],l[18]) * 1.0 / (1<<14)

        self.data[8] = two_bytes(l[19],l[20]) * 1.0 / (1<<14)

    elif self.type == 6:   # heading

        self.data[0] = four_bytes(l[3],l[4],l[5],l[6]) * 1.0 / (1<<16)

    else:   # unsupported

        pass



def display(self):

    if self.type == 0:

        print 'accel: %7.3f %7.3f %7.3f' % \

            (self.data[0], self.data[1], self.data[2])

    elif self.type == 1:

        print 'gyro: %9.5f %9.5f %9.5f' % \

            (self.data[0], self.data[1], self.data[2])

    elif self.type == 2:

        print 'compass: %7.4f %7.4f %7.4f' % \

            (self.data[0], self.data[1], self.data[2])

    elif self.type == 3:

        print 'quat: %7.4f %7.4f %7.4f %7.4f' % \

            (self.data[0], self.data[1], self.data[2], self.data[3])

    elif self.type == 4:

        print 'euler: %7.4f %7.4f %7.4f' % \

            (self.data[0], self.data[1], self.data[2])

    elif self.type == 5:

        print 'rotation matrix: \n%7.3f %7.3f %7.3f\n%7.3f %7.3f %7.3f\n%7.3f %7.3f %7.3f' % \

            (self.data[0], self.data[1], self.data[2], self.data[3], \

             self.data[4], self.data[5], self.data[6], self.data[7], \

             self.data[8])

    elif self.type == 6:

        print 'heading: %7.4f' % self.data[0]

    else:

        print 'what?'



class quat_packet (object):

def __init__(self, l):

    self.l = l

    self.q0 = four_bytes(l[3],l[4],l[5],l[6]) * 1.0 / (1<<30)

    self.q1 = four_bytes(l[7],l[8],l[9],l[10]) * 1.0 / (1<<30)

    self.q2 = four_bytes(l[11],l[12],l[13],l[14]) * 1.0 / (1<<30)

    self.q3 = four_bytes(l[15],l[16],l[17],l[18]) * 1.0 / (1<<30)

def display_raw(self):

    l = self.l

    print "".join(

        [ str(ord(l[0])), " "] + \

        [ str(ord(l[1])), " "] + \

        [ str(ord(a)).ljust(4) for a in 

                            [ l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10] ] ] + \

        [ str(ord(a)).ljust(4) for a in 

                            [ l[8], l[9], l[10] , l[11], l[12], l[13]] ]

        )



def display(self):

    if 1:

        print "qs " + " ".join([str(s).ljust(15) for s in

            [ self.q0, self.q1, self.q2, self.q3 ]])

    if 0:

        euler0, euler1, euler2 = self.to_q().get_euler()

        print "eulers " + " ".join([str(s).ljust(15) for s in

            [ euler0, euler1, euler2 ]])

    if 0:

        euler0, euler1, euler2 = self.to_q().get_euler()

        print "eulers " + " ".join([str(s).ljust(15) for s in

            [ (euler0 * 180.0 / 3.14159) - 90 ]])



def to_q(self):

    return Quaternion(self.q0, self.q1, self.q2, self.q3)

# =============== MAIN ======================



if __name__ == "__main__":

if len(sys.argv) == 2:

    comport = int(sys.argv[1]) - 1

else:

    print "usage: " + sys.argv[0] + " port"

    sys.exit(-1)



pygame.init()

viewer = cube_packet_viewer()

debug  = debug_packet_viewer()

data   = data_packet_viewer()



reader = eMPL_packet_reader(comport, 

            quat_delegate = viewer, 

            debug_delegate = debug, 

            data_delegate = data)



while 1:

    event = pygame.event.poll()

    # TODO: Allow exit via keystroke.

    if event.type == pygame.QUIT:

        viewer.close()

        break

    if event.type == pygame.KEYDOWN:

        reader.write(pygame.key.name(event.key))

    reader.read()

    viewer.loop(event)

    debug.loop(event)

    data.loop(event)



    # TODO: If system load is too high, increase this sleep time.

    pygame.time.delay(0)

---------------- Full file below of pyserial -----------

#! python

import ctypes
import time
from serial import win32

import serial
from serial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError


class Serial(SerialBase):
"""Serial port implementation for Win32 based on ctypes."""

BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
             9600, 19200, 38400, 57600, 115200)

def __init__(self, *args, **kwargs):
    super(SerialBase, self).__init__()
    self._port_handle = None
    self._overlapped_read = None
    self._overlapped_write = None
    SerialBase.__init__(self, *args, **kwargs)

def open(self):
    """\
    Open port with current settings. This may throw a SerialException
    if the port cannot be opened.
    """
    if self._port is None:
        raise SerialException("Port must be configured before it can be used.")
    if self.is_open:
        raise SerialException("Port is already open.")
    # the "\\.\COMx" format is required for devices other than COM1-COM8
    # not all versions of windows seem to support this properly
    # so that the first few ports are used with the DOS device name
    str port = self.name
    try:
        if port.upper().startswith('COM') and int(port[3:]) > 8:
            port = '\\\\.\\' + port
    except ValueError:
        # for like COMnotanumber
        pass
    self._port_handle = win32.CreateFile(
            port,
            win32.GENERIC_READ | win32.GENERIC_WRITE,
            0,  # exclusive access
            None,  # no security
            win32.OPEN_EXISTING,
            win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
            0)
    if self._port_handle == win32.INVALID_HANDLE_VALUE:
        self._port_handle = None    # 'cause __del__ is called anyway
        raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))

    try:
        self._overlapped_read = win32.OVERLAPPED()
        self._overlapped_read.hEvent = win32.CreateEvent(None, 1, 0, None)
        self._overlapped_write = win32.OVERLAPPED()
        #~ self._overlapped_write.hEvent = win32.CreateEvent(None, 1, 0, None)
        self._overlapped_write.hEvent = win32.CreateEvent(None, 0, 0, None)

        # Setup a 4k buffer
        win32.SetupComm(self._port_handle, 4096, 4096)

        # Save original timeout values:
        self._orgTimeouts = win32.COMMTIMEOUTS()
        win32.GetCommTimeouts(self._port_handle, ctypes.byref(self._orgTimeouts))

        self._reconfigure_port()

        # Clear buffers:
        # Remove anything that was there
        win32.PurgeComm(
                self._port_handle,
                win32.PURGE_TXCLEAR | win32.PURGE_TXABORT |
                win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
    except:
        try:
            self._close()
        except:
            # ignore any exception when closing the port
            # also to keep original exception that happened when setting up
            pass
        self._port_handle = None
        raise
    else:
        self.is_open = True

-----------#### rest of file removed for space------


回答1:


To answer 1) Because this relies on the hardware available, it is perfectly possible that the test code worked in the environment it was written on, but doesn't work in your environment - may be quite likely if you are on Windows and this was written on Linux. The code uses port 0 - don't know how that maps to COM1 etc.

2) On Windows, COM ports used to have DOS names like COM1, COM2 - i.e. A string, not an int (they aren't like TCP/IP port numbers). More recently in Windows there is the \\.\COMnotanumber format which allows a more generic name, I've seen these used by a USB to serial converter. Having had a quick look at the source code of pyserial SerialBase in serialutil.py, it's a bit odd IMO, because AFAICT self.name only gets set when you use an explicit port setting by calling self.port(portname). You might want to try intializing the serial port instance with serport = Serial(0) then explicitly calling serport.port('COM1') (or whatever your port name is instead of COM1).




回答2:


You may have the wrong version of serialwin32.py. I had the same error messages until I tried a different version. I am using 2.7 from here https://pypi.python.org/pypi/pyserial/2.7. Then I simply typed 'empl-client.py 8' and the error messages were gone. I also did not have the driver installed for the 'Embedded MotionApps' device. So, I found the eMPL_CDC.inf in the motion_driver_6.12 folder and installed it through device manager.

Now the problem I have is that the Embedded MotionApps device continuously connects and reconnects in Windows. Pygame is now running though but just sits there with a black screen. Invensense tell me that means it is connected and waiting for data.

It looks like there is data on the I2C bus and if the port would stay connected perhaps it might work. Though the data disappears from the bus when the port disconnects, so maybe the complete program is resetting. Actually there is a msp430_reset() function within the code and it does look like that is being called.




回答3:


The possibility to use numbers as ports has been removed in pySerial 3.x. Use device names (strings) instead, e.g. "/dev/ttyS0", "COM4" etc.

Those numbers were not consistent across operating systems and sometimes did not even include all devices. You can use the serial.tools.list_port module to enumerate actually available serial ports on most operating systems.



来源:https://stackoverflow.com/questions/34574311/pyserial-serialwin32-py-has-attribute-error

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!