Our problem is that if an error occurs during execution the serial port
does not get released (the port is opened at the start of the app). We
have tried many things to get the port to close but the only thing we
can do is to shut PyScriptor down everytime we want to run again.
Shutting down PyScripter releases the serial port so that we can
re-open it during execution.
I've included a code snippet from serialwin32.py (from pySerial
package). Refer to the "exception" block, it is the error that is
occurring.
Here is the error that is displayed in PyScripter: "Serial Exception:
could not open port: (5, 'CreateFile', 'Access is denied.')
----------------------------
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.")
self.hComPort = None
try:
self.hComPort = win32file.CreateFile(self.portstr,
win32con.GENERIC_READ | win32con.GENERIC_WRITE,
0, # exclusive access
None, # no security
win32con.OPEN_EXISTING,
win32con.FILE_ATTRIBUTE_NORMAL |
win32con.FILE_FLAG_OVERLAPPED,
None)
except Exception, msg:
self.hComPort = None #'cause __del__ is called anyway
raise SerialException("could not open port: %s" % msg)
# Setup a 4k buffer
win32file.SetupComm(self.hComPort, 4096, 4096)
----------------
Do you know of anything we can do to get around this issue?
Regards,
Mike S.
What you can do in PyScripter is run the scripts that use the PySerial
using the Run, External Run menu option. In that case the behaviour
would be very similar to that of running the script in a Command Window.
If I disable "Clean up sys.modules after run" in IDE options my Comm
Port problem appears to goes away.
Please let me know what you think about this. Do you think there is
still a problem with pySerial? I'd be glad to continue working this
issue. It is a big one for us.
Thanks,
Mike S.
This is what PyScripter does when running a script:
def run(self, cmd, globals=None, locals=None):
import bdb
import sys
import __main__
maindictcopy = __main__.__dict__.copy()
sysmodulescopy = sys.modules.copy()
if globals is None:
globals = __main__.__dict__
if locals is None:
locals = globals
try:
try:
bdb.Bdb.run(self, cmd, globals, locals)
except SystemExit:
pass
finally:
if self.CleanupMaindict:
__main__.__dict__.clear()
__main__.__dict__.update(maindictcopy)
if self.CleanupSysModules:
sys.modules.clear()
sys.modules.update(sysmodulescopy)
As you can see if CleanupSysModules is set then it restores the state
of sys.modules before the run. One thing is for sure that the port is
not closed by PySerial. I noticed that the following code is commented
out in serialwin32.py:
#~ def __del__(self):
#~ self.close()
Shouldn't this code be in place? It is not a problem if you run a
stand-alone application since Windows closes all open handles when the
application terminates, but if you want to run the code from within the
IDE this matters since the open handle to the port is not closed and it
blocks further runs from accessing the port. So, I would recommend to
try to enable the above code to see whether it makes a difference or
else try to close the port explicitly.