can_logger.py dose not write to file.

Issue #72 resolved
Mathias Giacomuzzi created an issue

So I think there is something wrong with the current implementation of the can_logger. So tried to start a can logger with

python can_logger.py  -f ./log.txt

So here I get nothing.

python can_logger.py 

Here I get my messages.

So I dive into the implementation and there I found out that the file write has no flush. And what I read in the docs someone must close the file, otherwise it will not write it if no flush is used. So I see the Printer hast a del (destructor) which should close the file. But this destructor will never be called in this implementation. See also here: http://stackoverflow.com/questions/865115/how-do-i-correctly-clean-up-a-python-object

So dose this really work for other?

Is there a way to change the Listeners to the with statement usage? So I tried that but then I have some problem with the rx thread.

    with can.Printer(results.log_file) as printer:
        notifier = can.Notifier(bus, [printer], timeout=0.1)

        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            print('Shutdown Bus and Exit.')
            bus.shutdown()

And in CAN.py I add:

    def __enter__(self):
        print("enter..")
        return self

    def __exit__(self, type, value, traceback):
        print("exit..")
        self.output_file.write("\n")
        if self.output_file:
            print("close exit ..")
            self.output_file.close()

It works now but I get an exception on close.

(py35_python_can) e:\bitbucket_hg\python-can\bin>python can_logger.py  -f ./temp.txt
Can Logger (Started on 2016-07-19 09:49:10.052735)

enter..
Shutdown Bus and Exit.
exit..
close exit ..
Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python35\lib\threading.py", line 914, in _bootstrap_inner
    self.run()
  File "C:\Python35\lib\threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "e:\bitbucket_hg\python-can\can\notifier.py", line 32, in rx_thread
    msg = self.bus.recv(self.timeout)
  File "e:\bitbucket_hg\python-can\can\interfaces\pcan.py", line 169, in recv
    raise Exception(self._get_formatted_error(result[0]))
Exception: Der PCAN Kanal ist nicht initialisiert oder der Initialisierungsvorgang ist fehlgeschlagen

Exception ignored in: <bound method Printer.__del__ of <can.CAN.Printer object at 0x00000000015C3550>>
Traceback (most recent call last):
  File "e:\bitbucket_hg\python-can\can\CAN.py", line 97, in __del__
ValueError: I/O operation on closed file.

(py35_python_can) e:\bitbucket_hg\python-can\bin>

mathias

Comments (3)

  1. Brian Thorne repo owner

    Thanks for the bug report Mathias, sorry it has taken me a while to look at it.

    A context manager would indeed be a much nicer api for the Listeners.

    In this case I wonder if we gain anything having the Listener's extra thread. Perhaps we can just connect the Printer to the Bus. E.g:

        with can.Printer(results.log_file) as printer:
            for msg in bus:
                printer.on_message_received(msg)
    

    The problem in your solution appears to be that after __exit__ but before the whole program has stopped a message is received by the printer.

    I belive the fix being that __exit__ should set something in the Printer that disables handling messages in the on_message_received method. For instance a finished boolean. If you have this all going would you mind contributing it back? Feel free to be more ambitious with changes if you wish!

  2. Log in to comment