Myk
Myk

Reputation: 6215

Python Noob - Silly Question? Works in Python Interpreter, not from CLI

I am hoping this is a simple stupid noob mistake that can be fixed with the addition of a single line of code somewhere.

I'm using pySerial to read in serial data from a USB port and print it out to standard output. I'm running Mac OSX 10.6. I open terminal and type "python", then the following:

>>> import serial;
>>> ser = serial.Serial('/dev/tty.usbserial-XXX', 9600, timeout=1);
>>> while True:
>>>      if ser.inWaiting() > 0:
>>>            ser.readline();
>>> [done, I hit enter...]

This works beautifully. It starts outputting my serial data nicely, exactly as I'd expect it to. Great, I think, let me put this into its own script with command line arguments and then I can call it any time I want to:

import sys;
import serial;

serialPort = sys.argv[1]
baudRate = sys.argv[2]

ser = serial.Serial(serialPort, baudRate, timeout=1)

while True:
    if ser.inWaiting() > 0:
        ser.readline()

On the command line, I type "python myScript.py [my serial port] 9600" and sit back and wait for a beautiful flow of serial data - but nothing comes out. It just kinda hangs until I kill the process.

I thought, well maybe for some reason it's not working - so I put some debugging prints into the code. I update my while loop to look like this:

 while True:
    print("looping...")
    print(ser.inWaiting());
    if ser.inWaiting() > 0:
        ser.readline()

I run it again, and I get a repeating output stream of "Looping..." and "0". I think, well maybe there's something wrong with my command line arguments - so I hard-coded the port and the baud rate into the script, same thing.

So, why would this be the case? Is my use of while True: somehow blocking the script from accepting serial data? Is there a better way to do this?

I'm a complete Python noob. I am writing this script in order to create a faster way to communicate between Adobe AIR and an Arduino board. I'm hoping there's a magic bullet I can drop in here to make it work - is there?

Upvotes: 3

Views: 1146

Answers (3)

bukzor
bukzor

Reputation: 38462

Is my use of while True: somehow blocking the script from accepting serial data?

Nope. This is very standard practice and doesn't affect I/O in any way. while True is very much equivalent to while 1 in C.

Is there a better way to do this?

I'm concerned about your arguments, like others. This should be more reliable overall:

from sys import argv
from serial import Serial

try:
    baudRate = int(argv[-1])
    serialPort = argv[1:-1]
except ValueError:
    #some nice default
    baudRate = 9600
    serialPort = argv[1:]

#support paths with spaces. Windows maybe?
serialPort = ' '.join(serialPort)
if not serialPort:
    exit("Please specify a serial port")

print( "reading from %r@%i ..." % (serialPort, baudRate) )
ser = Serial(serialPort, baudRate, timeout=1)    
while True:
    if ser.inWaiting() > 0:
        print( ser.readline() )

If that doesn't help you, please check that you are using the same interpreter by running these lines in a script and in the CLI.

import sys
print("Executable: " + sys.executable)
print("Version: " + sys.version)

Upvotes: 0

Benn
Benn

Reputation: 1420

Is it printing anything? I'd assume it would print:

looping...
<ser.inWaiting() val>

And then nothing. Add a print statement so it looks like

print ser.readline()

and see if that works. I'm guessing that the interpreter is printing the returned strings when you do it as a command, but in a script the returned strings from readline() are getting discarded.

Upvotes: 1

Dana the Sane
Dana the Sane

Reputation: 15198

In your 1st example, baud rate is an integer but in the 2nd, you don't not convert sys.argv[2] from a string. Try this ser = serial.Serial(serialPort, int(baudRate), timeout=1).

Upvotes: 1

Related Questions