Conversing with the user

What will we cover?
How to prompt the user to enter data and how to read that data once it is entered. We will show how to read both numerical and string based data. Also we look at how to read data input as command line arguments.

So far our programs have only dealt with static data. Data that, if need be, we can examine before the program runs and thus write the program to suit. Most programs aren't like that. Most programs expect to be driven by a user, at least to the extent of being told what file to open, edit etc. Others prompt the user for data at critical points. Let's see how that can be done before we progress any further.

>>> print raw_input("Type something: ")

As you see raw_input simply displays the given prompt and captures whatever the user types in response. Print then displays that response. We could instead assign it to a variable:

resp = raw_input("What's your name? ")
print "Hi, %s, nice to meet you" % resp 

raw_input has a cousin called input. The difference is that raw_input collects the characters the user types and presents them as a string, whereas input collects them and tries to form them into a number. For example if the user types '1','2','3' then input will read those 3 characters and convert them into the number 123.

Let's use input to decide which multiplication table to print:

multiplier = input("Which multiplier do you want? Pick a number ")
for j in range(1,13):
   print "%d x %d = %d" % (j, multiplier, j * multiplier)

Unfortunately there's a big snag to using input. That's because input doesn't just evaluate numbers but rather treats any input as Python code and tries to execute it. Thus a knowledgable but malicious user could type in a Python command that deleted a file on your PC! For this reason it's better to stick to raw_input and convert the string into the data type you need using Python's built in conversion functions. This is actually pretty easy:

multiplier = int(raw_input("Which multiplier do you want? Pick a number "))
for j in range(1,13):
   print "%d x %d = %d" % (j, multiplier, j * multiplier)

You see? We just wrapped the raw_input call in a call to int. It has the same effect as using input but is much safer. There are other conversion functions too so that you can convert to floats etc as well.

BASIC INPUT

In BASIC the INPUT statement reads input from the user thus:

INPUT "What multiplier do you want, pick a number ";M
FOR J = 1 to 12
    PRINT M "x" J "= " M*J
NEXT J

As you see its very similar to Python except you put the variable at the end. Also BASIC uses INPUT for both numbers and strings. There are usually a few extra features in BASIC's INPUT statement. You should look at the documentation for your particular version.

Reading input in Tcl

Tcl has its own input mechanism, which is based around files (which may include the standard input and output 'files') and a command called gets. This reads input from the specified file which in our case will be stdin.
[ Note: This program will not work from the standard tclsh80 or wish80 prompt. Instead you will need to type it into a file (say input.tcl) and run it from the command prompt like so:

    C:\PROJECTS\Tcl>tclsh80 input.tcl
]

The Tcl version of our program looks like this:

puts -nonewline stdout "What multiplier do you want? "
flush stdout
set mult [gets stdin]
for {set j 1} {$j <= 12} {incr j} {
    puts [format " %d x %d = %d" $j $mult [expr $mult * $j] ]
    }

The -nonewline option to puts simply prevents the cursor from moving to the next line after displaying the prompt message. flush forces stdout to write its contents immediately to ensure that it appears on screen. The for loop is almost identical to the version we saw in the loops section.

A word about stdin and stdout

NOTE: stdin is a bit of jargon for the standard input device (usually the keyboard). It is made to look like a file (we'll get to those shortly) for consistency with file handling code.

In Python it lives in the sys module and is called sys.stdin and raw_input() uses it automatically. Tcl can read from any file using gets (short for getstring). You can do the same in Python, try this:

import sys
print "Type a value: ",  # comma prevents newline
value = sys.stdin.readline()  # use stdin explicitly
print value

It is almost identical to:

print raw_input("Type a value: ")

The advantage of the explicit vesion is that you can do fancy things like make stdin point to a real file so the program reads its input from the file rather than the terminal - this can be useful for long testing sessions whereby instead of sitting typing each input as requested we simply let the program read its input from a file. [ This has the added advantage of ensuring that we can run the test repeatedly, sure that the input will be exactly the same eaach time, and so hopefully will the output. This technique of repeating previous tests to ensure that nothing got broken is called regression testing by programmers. ]

Finally there is also a sys.stdout 'file' that can likewise be redirected, this time to a file. print is equivalent to:

sys.stdout.write("Hello world\n") # \n= newline

Obviously if stdout did not refer to the screen then the output would be written to a file. This is how the operating system commands work when we use redirection at the command prompt:

C:> dir
C:> dir > dir.txt

The first command prints a directory listing to the screen. The second prints it to a file. By using the '>' sign we tell the program to redirect stdout to the file dir.txt.

Command Line Parameters

One other type of input is from the command line. For example when you run your text editor like:

EDIT Foo.txt

How does the editor read the filename?

In most languages the system provides an array or list of strings containing the command line words. Thus the first element will contain the command itself, the second element will be the first argument, etc. There is usually some kind of magic variable that holds the number of elements in the list.

In Python that list is held by the sys module and called argv (for 'argument values'). We can extract the elements using indexing or by iterating over the list, thus:

import sys
for item in sys.argv:
    print item
    
print "The first argument was:", sys.argv[1]

Note that this only works if you put it in a file (say args.py) and execute it from the operating system prompt like this:

C:\Python\PROJECTS> python args.py 1 23 fred
args.py
1
23
fred
The first argument was: 1
C:\PYTHON\PROJECTS>

Tcl's Command line

Tcl has a similar scheme with 3 variables:

  • argv0 - the command name,
  • argv - a string containing the rest of the command line and
  • argc - containing the number of words in argv

    An example of accessing the command line arguments in Tcl is:

    puts "the command was: $argv0"
    puts "The first argument was:  [lindex $argv 0]"
    

    Once again you will need to run this as a script from the operating system command prompt and provide some sample arguments.

    And BASIC

    While Tcl does not appear to have an 'input' equivalent, BASIC does not seem to have an argv equivalent although it would be possible to use operating system features to access them - for example they are stored in an environment variable under DOS so you can use the GETENV function. But that's far too advanced for this course however, and I recommend that in BASIC programs you prompt the user for the values interactively.

    That's really as far as we'll go with user input in this course. It's very primitive but you can write useful programs with it. In the early days of Unix or PCs it's the only kind of interaction you got. Python, Tcl and BASIC (in its 'Visual' incarnation) are all capable of writing sophisticated GUI programs with windows, dialogs etc... but that's a bit too advanced for this course. Having said that, the case study does provide a brief example of getting input via a GUI in Python but we won't be explaining too much about how it works. There are Web tutorials available for doing that once you get a good grounding in the essentials, I'll list some of them in the references page.

    Points to remember
    • Use input for reading numbers, raw_input for reading characters/strings.
    • Both input and raw_input can display a string to prompt the user.
    • BASIC's INPUT command can be used for any type of data.
    • Command line parameters can be obtained from the argv list imported from the sys module in Python, where the first item is the name of the program.
    • TCL uses the similarly named argv list to get it's command line data, but the program name is in the separate argv0
    • The __name__ variable will be set to "__main__" if the module has been run from the command line (or double clicked in Windows).

    Previous  Next  Contents


    If you have any questions or feedback on this page send me mail at: alan.gauld@btinternet.com