Skip to content
This repository has been archived by the owner on Mar 28, 2020. It is now read-only.

calls to exit() rather than sys.exit() in pymata_core.py #81

Closed
ericwertz opened this issue Oct 14, 2018 · 21 comments
Closed

calls to exit() rather than sys.exit() in pymata_core.py #81

ericwertz opened this issue Oct 14, 2018 · 21 comments

Comments

@ericwertz
Copy link

Note: I previously, mistakenly submitted this bug against "pymata" rather than here in "pymata-aio".
I think/hope that I've closed that bug report out... but perhaps not. Apologies.

During the course of some trying to track down some almost-exclusively Windows-specific runtime problems, I've hit one or more paths where exit() is being called, rather than what should be sys.exit() in pymata_core. A quick search finds that there are two such calls currently in pymata_core.py at lines 990 and 1869.

Since we're talking about calls to sys.exit(), there are numerous places where sys.exit(0) is called in non-happy paths that seem to be runtime errors, but for which no diagnostic messages are issued. Any of these that are hit would result in silent deaths, making them hard to track down if they're hit. At least a print() would help, and a full-on runtime error w/stack trace might even be more helpful in some of these contexts.

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 14, 2018

Any place where exit is called is in a location where unrecoverable occurred.

Let me comment on all of the places where exit is called:
line 287 - a print statement is generated.

lines 330 and 332 - there is no connectivity to the Arduino and the code is trying to close down asynio just above that. A print statement is generated in line 316.

line 395 generates a print statement.

lines 426, 432 and 434 a print statement is generated just above.

lines 464, 470 and 472 a print statement is generated just above.

line 990 - The only time that I am aware of that an exception is generated as a result of when shutdown() calls send_reset. If send_reset is called on its own and there is a problem in the call to _send_command, _send_command will issue a print statement. If shutdown is called, a print is generated.

line 1164 - there is a print statement above.

line 1427 - there is a print statement above.

line 1869 - there is a print statement above.

So, are you seeing unidentifed exits and if so, please let me know the scenario so I can try to reproduce it here.

Thanks

@ericwertz
Copy link
Author

ericwertz commented Oct 14, 2018 via email

@ericwertz
Copy link
Author

ericwertz commented Oct 14, 2018 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 14, 2018

I should probably change the exits to sys.exit for consistency. I will open up an issue so that I do so the next time I make a change.

I just ran the 2 following scripts both on Linux and Windows and both behave the same. I also ran a code inspection on both scripts in PyCharm and it does a strict check for any problems. None reported.

import time

print('hello')
time.sleep(1)
print('goodbye')
exit(0)

import time
import sys


print('hello')
time.sleep(1)
print('goodbye')
sys.exit(0)

I am going to close the issue, but feel free to add any comments and if this should reopened I will do so.

@MrYsLab MrYsLab closed this as completed Oct 14, 2018
@ericwertz
Copy link
Author

ericwertz commented Oct 14, 2018 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 14, 2018

@ericwertz I just opened issue #82 to track this.

Could you please remind about the failures on your student's laptops. Do they all fail in the same way?
If so, what is the failure again?

In issue #79 a user reported some problems. When he set the arduino_wait parameter to 5 seconds, things worked for him. I don't remember, did we try doing that for your students?

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 14, 2018

@ericwertz I can highly recommend PyCharm. I used to be a "debug by print guy", but having the IDE has made things some much easier and efficient.

You can get a free copy of their professional edition for both you and your students:
https://www.jetbrains.com/student/

One advantage of the professional version is that you can run a code on a remote python interpreter and debug it on your pc. I do that all the time when working with the Raspberry Pi. Makes life much easier ;-).

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 14, 2018

@ericwertz One more plug for Pycharm - if you get the student license, you also get access to all of their other products. The user interface is pretty much consistent across their product line, so you only have to go through the pain once. I have used WebStorm, IntelliJ (Java), and RubyMine. All work well.

@ericwertz
Copy link
Author

ericwertz commented Oct 14, 2018 via email

@ericwertz
Copy link
Author

ericwertz commented Oct 14, 2018 via email

@ericwertz
Copy link
Author

ericwertz commented Oct 14, 2018 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 14, 2018

Hi Eric,
Your attachments did not make it through. I think you may have the wrong email address. The correct one is MisterYsLab@gmail.com.

I am in the Eastern time zone of the U.S.

If you want a simple IDE you might want to look at the mu-editor https://codewith.mu/.
It is simple, does syntax checking for straight python, allows you to set breakpoints. Only thing is that it is python 3 only.

@ericwertz
Copy link
Author

ericwertz commented Oct 14, 2018 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 14, 2018

I haven't seen your screenshots yet, but some thoughts. Is it possible that there is another serial device that the PC thinks is available? pymata selects the first port that it can connect to so potentially could select the wrong port (but I have no reports of this happening). If you bring up the Arduino IDE and check the COM port it is using, is this the same one that pymata is selecting (close the Arduino IDE before running pymata)? They should be the same.

You may already have checked this out, but this Arduino page explains getting Arduino to work with Windows 10.
It is possible the driver is the culprit and that page explains how to install an Arduino USB/Serial driver.

I had a user who could not connect his micro:bit to my s2m program using Windows 10. He had to load the appropriate driver to get things to work. Supposedly Windows is already loaded with the correct driver, but in his case, it wasn't. I love Windows ;-).

@ericwertz
Copy link
Author

ericwertz commented Oct 15, 2018 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 15, 2018

Hi Eric,
I haven't received your screenshots yet and don't see anything attached to this issue. BTW, could you send an email to MisterYsLab@gmail.com. I need to mention something to you, but don't wish to share it publicly here. I was very surprised to see something in my inbox when I woke this morning and would like to comment on it.

If your students are using Windows 7, then I believe they have to install the Arduino drivers. Also, I seem to remember, a long while back, that I had some funny things happen with Windows 10 with the USB/Serial stuff and that all disappeared after one of the many updates. This may not help, but your students should make sure their Windows 10 is up to date.

@ericwertz
Copy link
Author

ericwertz commented Oct 15, 2018 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 16, 2018

Here are some error conditions I have caught that might help to isolate the problem if they persist:

I am running blink.py as a test program for 1 & 2.

  1. No Arudino plugged in:
pymata_aio Version 2.25	Copyright (c) 2015-2018 Alan Yorinks All rights reserved.

Using COM Port:/dev/ttyS0

Initializing Arduino - Please wait... Traceback (most recent call last):
  File "/home/afy/PycharmProjects/pymata-aio/examples/blink.py", line 29, in <module>
    board = PyMata3()
  File "/home/afy/PycharmProjects/pymata-aio/pymata_aio/pymata3.py", line 68, in __init__
    self.core.start()
  File "/home/afy/PycharmProjects/pymata-aio/pymata_aio/pymata_core.py", line 302, in start
    print("\nArduino Firmware ID: " + firmware_version)
TypeError: can only concatenate str (not "NoneType") to str
  1. Arduino plugged in but a non-Firmata sketch is loaded on Arduino:
pymata_aio Version 2.25	Copyright (c) 2015-2018 Alan Yorinks All rights reserved.

Using COM Port:/dev/ttyACM0

Initializing Arduino - Please wait... Traceback (most recent call last):
  File "/home/afy/PycharmProjects/pymata-aio/examples/blink.py", line 29, in <module>
    board = PyMata3()
  File "/home/afy/PycharmProjects/pymata-aio/pymata_aio/pymata3.py", line 68, in __init__
    self.core.start()
  File "/home/afy/PycharmProjects/pymata-aio/pymata_aio/pymata_core.py", line 302, in start
    print("\nArduino Firmware ID: " + firmware_version)
TypeError: can only concatenate str (not "NoneType") to str
  1. Here is a program with signal handling to exit cleanly when the user hits Control-C:
from pymata_aio.pymata3 import PyMata3
from pymata_aio.constants import Constants
import sys
import signal
value = 0

def my_callback(data):
    global value
    # data[0] is the pin number and data[1] is the changed value
    value = (data[1])

try:
    board = PyMata3()
    board.set_pin_mode(2, Constants.ANALOG, my_callback)
except Exception:
    print('ooops')
    raise

# Signal handler to trap control C
def _signal_handler(sig, frame):
    if board is not None:
        print('\nYou pressed Ctrl+C')
        sys.exit(1)


signal.signal(signal.SIGINT, _signal_handler)
signal.signal(signal.SIGTERM, _signal_handler)

# add SIGALRM if platform is not windows
if not sys.platform.startswith('win32'):
    signal.signal(signal.SIGALRM, _signal_handler)


while True:
    print(value)
    board.sleep(.1)

and its output:

/usr/local/bin/python3.7 /home/afy/PycharmProjects/pymata-aio/examples/comms_loss.py

pymata_aio Version 2.25	Copyright (c) 2015-2018 Alan Yorinks All rights reserved.

Using COM Port:/dev/ttyACM0

Initializing Arduino - Please wait... 
Arduino Firmware ID: 2.5 FirmataPlus.ino
Auto-discovery complete. Found 20 Digital Pins and 6 Analog Pins


0
702
702
702
702
702
702

You pressed Ctrl+C
  1. Now the same program with control-c handling removed:
from pymata_aio.pymata3 import PyMata3
from pymata_aio.constants import Constants
import sys
value = 0

def my_callback(data):
    global value
    # data[0] is the pin number and data[1] is the changed value
    value = (data[1])

try:
    board = PyMata3()
    board.set_pin_mode(2, Constants.ANALOG, my_callback)
except Exception:
    print('ooops')
    raise

# Signal handler to trap control C
def _signal_handler(sig, frame):
    if board is not None:
        print('\nYou pressed Ctrl+C')
        sys.exit(1)

while True:
    print(value)
    board.sleep(.1)

and its output:

/usr/local/bin/python3.7 /home/afy/PycharmProjects/pymata-aio/examples/comms_loss.py

pymata_aio Version 2.25	Copyright (c) 2015-2018 Alan Yorinks All rights reserved.

Using COM Port:/dev/ttyACM0

Initializing Arduino - Please wait... 
Arduino Firmware ID: 2.5 FirmataPlus.ino
Auto-discovery complete. Found 20 Digital Pins and 6 Analog Pins


0
702
702
702
702
702
702
702
702
702
702
702
702
702
702
702
702
Traceback (most recent call last):
  File "/home/afy/PycharmProjects/pymata-aio/examples/comms_loss.py", line 26, in <module>
    board.sleep(.1)
  File "/home/afy/PycharmProjects/pymata-aio/pymata_aio/pymata3.py", line 616, in sleep
    self.loop.run_until_complete(task)
  File "/usr/local/lib/python3.7/asyncio/base_events.py", line 555, in run_until_complete
    self.run_forever()
  File "/usr/local/lib/python3.7/asyncio/base_events.py", line 523, in run_forever
    self._run_once()
  File "/usr/local/lib/python3.7/asyncio/base_events.py", line 1722, in _run_once
    event_list = self._selector.select(timeout)
  File "/usr/local/lib/python3.7/selectors.py", line 468, in select
    fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt

@ericwertz
Copy link
Author

ericwertz commented Oct 21, 2018 via email

@MrYsLab
Copy link
Owner

MrYsLab commented Oct 21, 2018

Eric,
By adding a small delay before starting the while loop, solves this problem - it give Firmata a chance to complete its first scan of the Ananlog ports. This is shown below with the call to board.sleep(.04). The output is below the code.

from pymata_aio.pymata3 import PyMata3
from pymata_aio.constants import Constants
import sys
import signal
value = 0

def my_callback(data):
    global value
    # data[0] is the pin number and data[1] is the changed value
    value = (data[1])

try:
    board = PyMata3()
    board.set_pin_mode(2, Constants.ANALOG, my_callback)
except Exception:
    print('ooops')
    raise

# Signal handler to trap control C
def _signal_handler(sig, frame):
    if board is not None:
        print('\nYou pressed Ctrl+C')
        sys.exit(1)


signal.signal(signal.SIGINT, _signal_handler)
signal.signal(signal.SIGTERM, _signal_handler)

# add SIGALRM if platform is not windows
if not sys.platform.startswith('win32'):
    signal.signal(signal.SIGALRM, _signal_handler)

# added to let Firmata get to its first scan
board.sleep(.04)

while True:
    print(value)
    board.sleep(.1)

Console output:

pymata_aio Version 2.26	Copyright (c) 2015-2018 Alan Yorinks All rights reserved.

Using COM Port:/dev/ttyACM0

Initializing Arduino - Please wait... 
Arduino Firmware ID: 2.5 FirmataPlus.ino
Auto-discovery complete. Found 20 Digital Pins and 6 Analog Pins


1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023
1023

You pressed Ctrl+C

Process finished with exit code 1

@ericwertz
Copy link
Author

ericwertz commented Oct 22, 2018 via email

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@ericwertz @MrYsLab and others