2010-06-12 33 views
5

Tôi đang cố gắng để kết nối với điện thoại của tôi từ Windows 7 máy tính của tôi sử dụng PySerial với đoạn mã sau:Làm cách nào để khắc phục lỗi "[Lỗi 6] Trình xử lý không hợp lệ". với PySerial

import wmi 
import serial 

c = wmi.WMI() 
modem = c.query("SELECT * FROM Win32_POTSModem").pop() 
ser = serial.Serial(modem.AttachedTo, modem.MaxBaudRateToSerialPort) 

try: 
    ser.write('at \r\n') 
    print ser.readline() 
finally: 
    ser.close() 

Nhưng nhận được lỗi sau trên các cuộc gọi ghi:

Traceback (most recent call last): 
    File "D:\Alasdair\Documents\Python Scripts\Phone Interface\test.py", line 14, in <module> 
    ser.write('at \r\n') 
    File "C:\Python26\Lib\site-packages\serial\serialwin32.py", line 255, in write 
    raise SerialException("WriteFile failed (%s)" % ctypes.WinError()) 
SerialException: WriteFile failed ([Error 6] The handle is invalid.) 

tôi đã thử kết nối với TeraTerm và nó hoạt động tốt, do đó, nó không phải là một vấn đề với kết nối với điện thoại chính nó.

Tôi đã tìm kiếm mọi lứa tuổi để tìm giải pháp nhưng chưa tìm ra bất kỳ thứ gì hoạt động. Ý tưởng nào?

Trả lời

4

Tôi đang ở trên cửa sổ 7 64 bit, với python 2.6 và nó cho tôi lỗi tương tự.

ser = serial.Serial(3,115200,timeout=1) 
ser.read() 
#or ser.write("whatever") 

Traceback (most recent call last): 
    File "<pyshell#3>", line 1, in <module> 
    ser.read(1) 
    File "build\bdist.win-amd64\egg\serial\serialwin32.py", line 236, in read 
    raise SerialException("ReadFile failed (%s)" % ctypes.WinError()) 
SerialException: ReadFile failed ([Error 6] The handle is invalid.) 

Khi sử dụng một chương trình tương tự sử dụng một thư viện c, cùng một cổng đáp ứng một cách chính xác. chuyện gì xảy ra ở đây thế? Âm thanh như một lỗi trong pyserial hoặc ctypes. Bạn đang sử dụng 64 bit?

mã nguồn để viết trong pyserial trông rất đơn giản

def write(self, data): 
     """Output the given string over the serial port.""" 
     if not self.hComPort: raise portNotOpenError 
     #~ if not isinstance(data, (bytes, bytearray)): 
      #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data))) 
     # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview 
     data = bytes(data) 
     if data: 
      #~ win32event.ResetEvent(self._overlappedWrite.hEvent) 
      n = win32.DWORD() 
      err = win32.WriteFile(self.hComPort, data, len(data), ctypes.byref(n), self._overlappedWrite) 
      if not err and win32.GetLastError() != win32.ERROR_IO_PENDING: 
       raise SerialException("WriteFile failed (%s)" % ctypes.WinError()) 

có lẽ là một vấn đề với ctypes 64 bit?


Cập nhật: Chắc chắn vấn đề 64 bit ít nhất đối với tôi. Tôi vừa cài đặt một phiên bản x86 của python (3.1 lần này), và bây giờ nó hoạt động tốt. Các ctype 64 bit tốt hơn chỉ có thể nhập các thư viện 64 bit. Nghe có vẻ rất lạ nhưng không thể tiếp cận được các thư viện hệ điều hành.

+0

OK, cảm ơn. Tôi đang sử dụng một phiên bản 64 bit của Python như bạn nghi ngờ. Tôi sẽ cho nó một phiên bản 32 bit. – alnorth29

6

Tôi vừa khắc phục sự cố này trên các cửa sổ 64 bit (XP, Vista và 7).

Vấn đề này là do quá trình truyền xử lý không hợp lệ, loại bỏ giá trị 32 bit trên 64 bit do các hàm python-win32 cũ. Nếu bạn gặp phải loại sự cố này, vui lòng sử dụng các hàm python-win32 mới được bao gồm trong mô-đun win32file, v.v. Vui lòng viết mã sau trên trang web-gói \ serial \ serialwin32.py.

#! python 
# Python Serial Port Extension for Win32, Linux, BSD, Jython 
# serial driver for win32 
# see __init__.py 
# 
# (C) 2001-2009 Chris Liechti <[email protected]> 
# this is distributed under a free software license, see license.txt 
# 
# Initial patch to use ctypes by Giovanni Bajo <[email protected]> 

import ctypes 
import win32 
import win32file 
import win32con 
import pywintypes 

from serialutil import * 

def device(portnum): 
    """Turn a port number into a device name""" 
    return 'COM%d' % (portnum+1) # numbers are transformed to a string 

class Win32Serial(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): 
     self.hComPort = 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.") 
     # 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 
     port = self.portstr 
     try: 
      if port.upper().startswith('COM') and int(port[3:]) > 8: 
       port = '\\\\.\\' + port 
     except ValueError: 
      # for like COMnotanumber 
      pass 
     self.hComPort = win32file.CreateFile(port, 
       win32con.GENERIC_READ | win32con.GENERIC_WRITE, 
       0, # exclusive access 
       None, # no security 
       win32con.OPEN_EXISTING, 
       win32con.FILE_ATTRIBUTE_NORMAL | win32con.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 %s: %s" % (self.portstr, ctypes.WinError())) 

     # Setup a 4k buffer 
     win32file.SetupComm(self.hComPort, 4096, 4096) 

     # Save original timeout values: 
     tos = win32file.GetCommTimeouts(self.hComPort) 
     self._orgTimeouts = win32.COMMTIMEOUTS(*tos) 
     self._rtsState = win32.RTS_CONTROL_ENABLE 
     self._dtrState = win32.DTR_CONTROL_ENABLE 

     self._reconfigurePort() 

     # Clear buffers: 
     # Remove anything that was there 
     win32file.PurgeComm(self.hComPort, 
          win32.PURGE_TXCLEAR | win32.PURGE_TXABORT | 
          win32.PURGE_RXCLEAR | win32.PURGE_RXABORT) 

     self._overlappedRead = pywintypes.OVERLAPPED() 
     self._overlappedRead.hEvent = win32.CreateEvent(None, 1, 0, None) 
     self._overlappedWrite = pywintypes.OVERLAPPED() 
     #~ self._overlappedWrite.hEvent = win32.CreateEvent(None, 1, 0, None) 
     self._overlappedWrite.hEvent = win32.CreateEvent(None, 0, 0, None) 
     self._isOpen = True 

    def _reconfigurePort(self): 
     """Set communication parameters on opened port.""" 
     if not self.hComPort: 
      raise SerialException("Can only operate on a valid port handle") 

     # Set Windows timeout values 
     # timeouts is a tuple with the following items: 
     # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier, 
     # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier, 
     # WriteTotalTimeoutConstant) 
     if self._timeout is None: 
      timeouts = (0, 0, 0, 0, 0) 
     elif self._timeout == 0: 
      timeouts = (win32.MAXDWORD, 0, 0, 0, 0) 
     else: 
      timeouts = (0, 0, int(self._timeout*1000), 0, 0) 
     if self._timeout != 0 and self._interCharTimeout is not None: 
      timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:] 

     if self._writeTimeout is None: 
      pass 
     elif self._writeTimeout == 0: 
      timeouts = timeouts[:-2] + (0, win32.MAXDWORD) 
     else: 
      timeouts = timeouts[:-2] + (0, int(self._writeTimeout*1000)) 
     win32file.SetCommTimeouts(self.hComPort, timeouts) 

     win32file.SetCommMask(self.hComPort, win32.EV_ERR) 

     # Setup the connection info. 
     # Get state and modify it: 
     comDCB = win32file.GetCommState(self.hComPort) 
     comDCB.BaudRate = self._baudrate 

     if self._bytesize == FIVEBITS: 
      comDCB.ByteSize  = 5 
     elif self._bytesize == SIXBITS: 
      comDCB.ByteSize  = 6 
     elif self._bytesize == SEVENBITS: 
      comDCB.ByteSize  = 7 
     elif self._bytesize == EIGHTBITS: 
      comDCB.ByteSize  = 8 
     else: 
      raise ValueError("Unsupported number of data bits: %r" % self._bytesize) 

     if self._parity == PARITY_NONE: 
      comDCB.Parity  = win32.NOPARITY 
      comDCB.fParity  = 0 # Disable Parity Check 
     elif self._parity == PARITY_EVEN: 
      comDCB.Parity  = win32.EVENPARITY 
      comDCB.fParity  = 1 # Enable Parity Check 
     elif self._parity == PARITY_ODD: 
      comDCB.Parity  = win32.ODDPARITY 
      comDCB.fParity  = 1 # Enable Parity Check 
     elif self._parity == PARITY_MARK: 
      comDCB.Parity  = win32.MARKPARITY 
      comDCB.fParity  = 1 # Enable Parity Check 
     elif self._parity == PARITY_SPACE: 
      comDCB.Parity  = win32.SPACEPARITY 
      comDCB.fParity  = 1 # Enable Parity Check 
     else: 
      raise ValueError("Unsupported parity mode: %r" % self._parity) 

     if self._stopbits == STOPBITS_ONE: 
      comDCB.StopBits  = win32.ONESTOPBIT 
     elif self._stopbits == STOPBITS_ONE_POINT_FIVE: 
      comDCB.StopBits  = win32.ONE5STOPBITS 
     elif self._stopbits == STOPBITS_TWO: 
      comDCB.StopBits  = win32.TWOSTOPBITS 
     else: 
      raise ValueError("Unsupported number of stop bits: %r" % self._stopbits) 

     comDCB.fBinary   = 1 # Enable Binary Transmission 
     # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE) 
     if self._rtscts: 
      comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE 
     else: 
      comDCB.fRtsControl = self._rtsState 
     if self._dsrdtr: 
      comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE 
     else: 
      comDCB.fDtrControl = self._dtrState 
     comDCB.fOutxCtsFlow  = self._rtscts 
     comDCB.fOutxDsrFlow  = self._dsrdtr 
     comDCB.fOutX   = self._xonxoff 
     comDCB.fInX    = self._xonxoff 
     comDCB.fNull   = 0 
     comDCB.fErrorChar  = 0 
     comDCB.fAbortOnError = 0 
     comDCB.XonChar   = XON 
     comDCB.XoffChar   = XOFF 
     win32file.SetCommState(self.hComPort, comDCB) 

    #~ def __del__(self): 
     #~ self.close() 

    def close(self): 
     """Close port""" 
     if self._isOpen: 
      if self.hComPort: 
       # Restore original timeout values: 
       win32file.SetCommTimeouts(self.hComPort, self._orgTimeouts) 
       # Close COM-Port: 
       win32file.CloseHandle(self.hComPort) 
       win32file.CloseHandle(self._overlappedRead.hEvent) 
       win32file.CloseHandle(self._overlappedWrite.hEvent) 
       self.hComPort = None 
      self._isOpen = False 

    def makeDeviceName(self, port): 
     return device(port) 

    # - - - - - - - - - - - - - - - - - - - - - - - - 

    def inWaiting(self): 
     """Return the number of characters currently in the input buffer.""" 
     flags = win32.DWORD() 
     comstat = win32.COMSTAT() 
     if not win32file.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)): 
      raise SerialException('call to ClearCommError failed') 
     return comstat.cbInQue 

    def read(self, size=1): 
     """Read size bytes from the serial port. If a timeout is set it may 
      return less characters as requested. With no timeout it will block 
      until the requested number of bytes is read.""" 
     if not self.hComPort: raise portNotOpenError 
     if size > 0: 
      win32.ResetEvent(self._overlappedRead.hEvent) 
      if not win32file.ClearCommError(self.hComPort): 
       raise SerialException('call to ClearCommError failed') 
      if self.timeout == 0: 
       n = min(comstat.cbInQue, size) 
       if n > 0: 
        rc,buf = win32file.ReadFile(self.hComPort, n, self._overlappedRead) 
        if win32.GetLastError() != win32.ERROR_IO_PENDING: 
         raise SerialException("ReadFile failed (%s)" % ctypes.WinError()) 
        err = win32.WaitForSingleObject(self._overlappedRead.hEvent, win32.INFINITE) 
        read = buf[:rc] 
       else: 
        read = bytes() 
      else: 
       rc,buf = win32file.ReadFile(self.hComPort, size, self._overlappedRead) 
       rc = win32file.GetOverlappedResult(self.hComPort, self._overlappedRead, True) 
       read = buf[:rc] 
     else: 
      read = bytes() 
     return bytes(read) 

    def write(self, data): 
     """Output the given string over the serial port.""" 
     if not self.hComPort: raise portNotOpenError 
     #~ if not isinstance(data, (bytes, bytearray)): 
      #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data))) 
     # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview 
     if data: 
      #~ win32event.ResetEvent(self._overlappedWrite.hEvent) 
      err,n = win32file.WriteFile(self.hComPort, data, self._overlappedWrite) 
      if not err and win32.GetLastError() != win32.ERROR_IO_PENDING: 
       raise SerialException("WriteFile failed (%s)" % ctypes.WinError()) 
      # Wait for the write to complete. 
      #~ win32.WaitForSingleObject(self._overlappedWrite.hEvent, win32.INFINITE) 
      n = win32file.GetOverlappedResult(self.hComPort, self._overlappedWrite, True) 
      if n != len(data): 
       raise writeTimeoutError 
      return n 
     else: 
      return 0 

    def flushInput(self): 
     """Clear input buffer, discarding all that is in the buffer.""" 
     if not self.hComPort: raise portNotOpenError 
     win32.PurgeComm(self.hComPort, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT) 

    def flushOutput(self): 
     """Clear output buffer, aborting the current output and 
     discarding all that is in the buffer.""" 
     if not self.hComPort: raise portNotOpenError 
     win32.PurgeComm(self.hComPort, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT) 

    def sendBreak(self, duration=0.25): 
     """Send break condition. Timed, returns to idle state after given duration.""" 
     if not self.hComPort: raise portNotOpenError 
     import time 
     win32.SetCommBreak(self.hComPort) 
     time.sleep(duration) 
     win32.ClearCommBreak(self.hComPort) 

    def setBreak(self, level=1): 
     """Set break: Controls TXD. When active, to transmitting is possible.""" 
     if not self.hComPort: raise portNotOpenError 
     if level: 
      win32.SetCommBreak(self.hComPort) 
     else: 
      win32.ClearCommBreak(self.hComPort) 

    def setRTS(self, level=1): 
     """Set terminal status line: Request To Send""" 
     if not self.hComPort: raise portNotOpenError 
     if level: 
      self._rtsState = win32.RTS_CONTROL_ENABLE 
      win32.EscapeCommFunction(self.hComPort, win32.SETRTS) 
     else: 
      self._rtsState = win32.RTS_CONTROL_DISABLE 
      win32.EscapeCommFunction(self.hComPort, win32.CLRRTS) 

    def setDTR(self, level=1): 
     """Set terminal status line: Data Terminal Ready""" 
     if not self.hComPort: raise portNotOpenError 
     if level: 
      self._dtrState = win32.DTR_CONTROL_ENABLE 
      win32.EscapeCommFunction(self.hComPort, win32.SETDTR) 
     else: 
      self._dtrState = win32.DTR_CONTROL_DISABLE 
      win32.EscapeCommFunction(self.hComPort, win32.CLRDTR) 

    def _GetCommModemStatus(self): 
     stat = win32.DWORD() 
     win32.GetCommModemStatus(self.hComPort, ctypes.byref(stat)) 
     return stat.value 

    def getCTS(self): 
     """Read terminal status line: Clear To Send""" 
     if not self.hComPort: raise portNotOpenError 
     return win32.MS_CTS_ON & self._GetCommModemStatus() != 0 

    def getDSR(self): 
     """Read terminal status line: Data Set Ready""" 
     if not self.hComPort: raise portNotOpenError 
     return win32.MS_DSR_ON & self._GetCommModemStatus() != 0 

    def getRI(self): 
     """Read terminal status line: Ring Indicator""" 
     if not self.hComPort: raise portNotOpenError 
     return win32.MS_RING_ON & self._GetCommModemStatus() != 0 

    def getCD(self): 
     """Read terminal status line: Carrier Detect""" 
     if not self.hComPort: raise portNotOpenError 
     return win32.MS_RLSD_ON & self._GetCommModemStatus() != 0 

    # - - platform specific - - - - 

    def setXON(self, level=True): 
     """Platform specific - set flow state.""" 
     if not self.hComPort: raise portNotOpenError 
     if level: 
      win32.EscapeCommFunction(self.hComPort, win32.SETXON) 
     else: 
      win32.EscapeCommFunction(self.hComPort, win32.SETXOFF) 

    def outWaiting(self): 
     """return how many characters the in the outgoing buffer""" 
     flags = win32.DWORD() 
     comstat = win32.COMSTAT() 
     if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)): 
      raise SerialException('call to ClearCommError failed') 
     return comstat.cbOutQue 

# assemble Serial class with the platform specific implementation and the base 
# for file-like behavior. for Python 2.6 and newer, that provide the new I/O 
# library, derive from io.RawIOBase 
try: 
    import io 
except ImportError: 
    # classic version with our own file-like emulation 
    class Serial(Win32Serial, FileLike): 
     pass 
else: 
    # io library present 
    class Serial(Win32Serial, io.RawIOBase): 
     pass 

# Nur Testfunktion!! 
if __name__ == '__main__': 
    s = Serial(0) 
    sys.stdout.write("%s\n" % s) 

    s = Serial() 
    sys.stdout.write("%s\n" % s) 

    s.baudrate = 19200 
    s.databits = 7 
    s.close() 
    s.port = 0 
    s.open() 
    sys.stdout.write("%s\n" % s) 
+1

Loại của một bài đăng zombie, nhưng tôi đã thử điều này, và bây giờ tôi nhận được một lỗi mới, cụ thể là self.port.flushInput() Tệp "C: \ Python27 \ lib \ site-packages \ serial \ serialwin32.py ", dòng 273, trong tuôn ra Nhập win32.PurgeComm (self.hComPort, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT) ctypes.ArgumentError: đối số 1: : loại sai – camperdave

+0

Vấn đề tương tự như @camperdave, có ai tìm ra điều này không? – Legogris

+0

Tôi có những tai ương tương tự.Tôi nghĩ rằng bản vá này có thời gian và địa điểm đã trôi qua, hãy thử 2,6, sau đó sẽ lùi lại trên 2,4. – meawoppl

1

tôi quan sát vấn đề này với Python 2.7 win7 x64, và PySerial 2.5 được cài đặt tự động từ easy_install.exe

Vấn đề không phải là ở đó với PySerial 2.4, vì vậy nếu mã của bạn là tương thích với 2.4, chỉ cần sử dụng thay vào đó một vấn đề được giải quyết. Lưu ý rằng bạn cũng phải sử dụng pywin32 và chọn phiên bản tương ứng với python của bạn (ví dụ: pywin32-216.win-amd64-py2.7.exe).

cũng Xem https://sourceforge.net/tracker/?func=detail&aid=2921959&group_id=46487&atid=446302%5D2921959

Các vấn đề liên quan