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.
  • The concepts of stdin and stdout
  • We look at command line interfaces and how to read data input as command line arguments.
  • We discuss the EasyGUI module for displaying simple data entry dialog boxes
  • 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. This aspect of programming is what is referred to as the User Interface and in commercial programs designing and building the user interface is a job for specialists trained in human machine interaction and ergonomics. The average programmer does not have that luxury so must make do with some common sense, and careful thought about how users will use the program. The most basic feature of a User Interface is displaying output and we have already covered the most primitive way of doing that via the Python print function (and JavaScript's write() function as well as the VBScript MsgBox dialog). The next step in User Interface design is to take input directly from the user. The simplest way to do that is for the program to ask for the input at run time, the next simplest way is for the user to pass the data in when he or she starts the program, finally we have graphical user interfaces (GUIs) with text entry boxes etc. In this topic we look mainly at the first two methods. We introduce GUI programming much later in the tutor because it is significantly more complex, however there is a module which allows us to do very basic GUI style dialog boxes for data entry in Python and we will briefly consider that.

    Let's see how we can get data from a user in a normal Python interactive session running in IDLE or an OS terminal. Afterwords we'll try doing the same in a program.

    Python user input

    We can get input from a user in Python like this:

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

    As you see input() simply displays the given prompt - "Type something" in this case - and captures whatever the user types in response. print() then displays that response. We could instead assign it to a variable:

    >>> resp = input("What's your name? ")
    

    And now we can print out whatever value was captured:

    >>> print( "Hi " + resp + ", nice to meet you" )
    

    Notice that this time I have chosen not to use the string formatting operator to display the value stored in the variable resp and have instead just inserted the value between two strings joining all three strings together using the string addition operator. The value of resp is the one captured from the user by input().

    Notice too in both examples the use of spaces inside the strings, both in the prompt given to input() but also in the output string. In particular notice the third part of the output string started with a comma followed by a space. It is a common mistake when producing output like that to get the spacing wrong so check carefully when testing your programs.

    This is great for reading strings. But what about other data types? The answer is that Python comes with a full set of data conversion functions that can convert a string to another data type. Obviously the data in the string has to be compatible with the type, otherwise you will get an error!

    As an example lets take our multiplication table example and modify it to read the multiplier value from the user:

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

    Here we read the value from the user then convert it to an integer using the int() conversion function. (You can use float() to convert to a floating point value too, should you need to). Here we did the conversion on a separate line to make it clearer what we were doing, but in practice this is so common that we usually just wrap the input() call inside the conversion, like this:

    >>> multiplier = int( 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 input() call inside the call to int().

    So what about using this in a real program? You recall the address book examples using a dictionary that we created in the raw materials topic? Let's revisit that address book now that we can write loops and read input data.

    # create an empty address book dictionary
    addressBook = {}
    
    # read entries till an empty string
    print()  # print a blank line 
    name = "-"  # non blank 
    while name != "":
       name = input("Type the Name(leave blank to finish): ")
       if name != "":
          entry = input("Type the Street, Town, Phone.(Leave blank to finish): ")
          addressBook[name] = entry
    
    # now ask for one to display
    name = "-"
    while name != "":
       name = input("Which name to display?(leave blank to finish): ")
       if name != "":
          print( name, addressBook[name] )
    

    That's our biggest program so far, and although the user interface design is a bit clunky it does the job. We will see how to improve it in a later topic. Some things to note in this program are the use of the boolean test in the while loops to determine when the user wants us to stop. Also note that whereas in the Raw Materials example we used a list to store the data as separate fields we have just stored it as a single string here. That's because we haven't yet covered how to break down a string into separate fields. We'll cover that in a later topic too. In fact the address book program will be cropping up from time to time through the rest of the tutorial as we gradually turn it into something useful.

    VBScript Input

    In VBScript the InputBox statement reads input from the user thus:

    <script type="text/vbscript">
    Dim Input
    Input = InputBox("Enter your name") 
    MsgBox ("You entered: " & Input)
    </script>
    

    The InputBox function simply presents a dialog with a prompt and an entry field. The contents of the entry field are returned by the function. There are various values that you can pass to the function such as a title string for the dialog box in addition to the prompt. If the user presses Cancel the function returns an empty string regardless of what is actually in the entry field.

    Here is the VBScript version of our Address book example.

    <script type="text/vbscript">
    Dim dict,name,entry  ' Create some variables.
    Set dict = CreateObject("Scripting.Dictionary")
    name = InputBox("Enter a name", "Address Book Entry")
    While name <> ""
       entry = InputBox("Enter Details - Street, Town, Phone number",
                        "Address Book Entry")
       dict.Add name, entry ' Add key and details.
       name = InputBox("Enter a name","Address Book Entry")
    Wend
    
    ' Now read back the values
    name = InputBox("Enter a name","Address Book Lookup")
    While name <> ""
       MsgBox(name & " - " & dict.Item(name))
       name = InputBox("Enter a name","Address Book Lookup")
    Wend
    </script>
    

    The basic structure is absolutely identical to the Python program although a few lines longer because of VBScript's need to pre-declare the variables with Dim and because of the need for a Wend statement to end each loop.

    Reading input in JavaScript

    JavaScript presents us with a challenge because it is a language primarily used within a web browser. We have a choice of using a simple input box like VBScript using the prompt() function or instead we can read from an HTML form element (or, in Internet Explorer, use Microsoft's Active Scripting technology to generate an InputBox dialog like the one used by VBScript). For variety I'll show you how to use the HTML form technique. If you are unfamiliar with HTML forms it might be worth finding an HTML reference or tutorial to describe them, alternatively just copy what I do here and hopefully it will be self explanatory. I will be keeping it very simple, I promise.

    The basic structure of our HTML example will be to put the JavaScript code in a function, although we haven't covered these yet. For now just try to ignore the function definition bits.

    <script type="text/javascript">
    function myProgram(){
       alert("We got a value of " + document.entry.data.value);
    }
    </script>
    
    <form name='entry'>
    <P>Type value then click outside the field with your mouse</P>
    <Input Type='text' Name='data' onChange='myProgram()'>
    </form>
    

    The program just consists of a single line that displays an alert box (very similar to VBScript's MsgBox) containing the value from the text field. The form displays a prompt message (within the <P></P> pair) and an input field. The input field has an attribute, onChange, that tells JavaScript that when the Input field changes it should execute the code given, in this case a call to myProgram. The form has a name, entry within the document context, and the Input field has a name, data within the entry form context. Thus within the JavaScript program we can refer to the value of the field as:

    document.entry.data.value
    

    I'm not going to show the address book example in JavaScript because the HTML aspects become more complex and the use of functions increases and I want to wait till we have covered those in their own topic.

    A Simple Python GUI Tool

    Creating a full blown GUI is quite a challenge and we need to cover a lot more material before being able to tackle it. However there is a module called EasyGui which makes it possible to at least interact with the user in a GUI like fashion via dialog boxes. EasyGui is not part of the standard Python library of modules but must be downloaded separately from:

    
    http://easygui.sourceforge.net/download
    

    You will also find a full tutorial on that site showing all of the different options possible. We will look at three of the simplest:

    The first thing to do is download the package and copy the python file into the site-packages folder within the Lib folder of your Python installation. On my PC that is:

    C:\Python3\Lib\site-packages
    

    Then you can import the module as usual and access the various functions. Here is a simple input/output sequence:

    import easygui
    name = easygui.enterbox("What is your name?", "Name Dialog")
    easygui.msgbox("Hello "+name+" nice to meet you!", "Greeting Dialog")
    

    Notice the use of the module name to prefix the functions. Also notice that the second string we passed into the function is displayed as the title of the dialog box.

    I think you will agree that using EasyGui is nearly as easy to use as input()! Let's finally look at our multiplication example with EasyGui:

    import easygui
    
    output = ""
    multiplier = easygui.integerbox("Which mltiplier?", "Multiplier dialog")
    for j in range(1,13):
      output = output + "%d x %d = %d\n" % (j, multiplier, j * multiplier)
    
    easygui.msgbox(output, "Multiplication table")
    

    There are many other options in EasyGui that will make your programs look much more like a GUI application. Experiment with the functions available and try to repeat some of our other examples, such as the address book using EasyGUI.

    Next we look at a different kind of user interaction that is used where the program just needs some initial values and then generates it's output with no further intervention from the user.


    A word about stdin and stdout

    NOTE: stdin is a bit of computer jargon for the standard input device (usually the keyboard). stdout refers to the standard output device (usually the screen). You will quite often see references to the terms stdin and stdout in discussions about programming. (There is a third, less commonly used term, stderr, which is where all console error messages are sent. Normally stderr appears in the same place as stdout.) These terms are often called data streams since data appears as a stream of bytes flowing to the devices. stdin and stdout are made to look like files (we'll get to those shortly) for consistency with file handling code.


    In Python they all live in the sys module and are called sys.stdin and sys.stdout. input() uses stdin automatically and print() uses stdout. We can also read from stdin and write to stdout directly and this can offer some advantages in terms of fine control of the input and output. Here is an example of reading from stdin:

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

    It is almost identical to:

    print( input("Type a value: ") )
    

    The advantage of the explicit version 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 each 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 here is an example of direct output to sys.stdout that can likewise be redirected to a file. print is nearly equivalent to:

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

    Of course we can usually achieve the same effects using format strings if we know what the data looks like but if we don't know what the data will look like till runtime then its often easier to just send it to stdout rather than try to build a complex format string at runtime.

    Redirecting stdin & stdout

    So how do we redirect stdin and stdout to files? We can do it directly within our program using the normal Python file handling techniques which we will cover shortly, but the easiest way is to do it via the operating system.


    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.

    We would do the same with a Python program like this:
    $ python myprogram.py > result.txt
    

    Which would run myprogram.py but instead of displaying the output on screen it would write it to the file result.txt. We could see the output later using a text editor like notepad.

    (Note that the $ prompt shown above is the standard for Linux users - just in case they were feeling neglected!)


    To get stdin to point at a file we simply use a < sign rather than a > sign. Here is a complete example:

    First create a file called echoinput.py containing the following code:

    import sys
    inp = sys.stdin.readline()
    while inp.strip() != '':
       print( inp )
       inp = sys.stdin.readline()
    

    Note: The strip() simply chops off the newline character that is retained when reading from stdin, input() does that for you as a convenience. You can now try running that from a command prompt:

    $ python echoinput.py
    

    The result should be a program that echos back anything you type until you enter a blank line.


    Now create a simple text file called input.txt containing some lines of text. Run the last program again, redirecting input from input.txt:

    $ python echoinput.py < input.txt
    

    Python echos back what was in the file. But you might recall that we said that print() and input() actually use stdin and stdout internally? That means we can replace the stdin stuff in echoinput.py with input() like this:

    inp = input()
    while inp != '':
       print( inp )
       inp = input()
    

    Which is much easier in most cases.


    By using this technique with multiple different input files we can quickly and easily test our programs for a variety of scenarios (for example bad data values or types) and do so in a repeatable and reliable manner. We can also use this technique to handle large volumes of data from a file while still having the option to input the data manually for small volumes using the same program. Redirecting stdin and stdout is a very useful trick for the programmer, experiment and see what other uses you can find for it.


    There is a known bug in Windows XP that breaks input redirection. (If anyone knows whether this has been fixed in Vista please let me know via the email link at the bottom of the page.) If you start your program by just typing in the script name, rather than explicitly typing in python before it, Windows will not display the results on the console! There is a registry hack to fix this on Microsoft's web site, although even the hack isn't quite correct! You need to look under HKEY_CURRENT USER instead of HKEY_LOCAL_MACHINE as recommended on the web page. My recommendation is to always explicitly invoke python when dealing with redirected input or output! (Thanks go to Tim Graber for spotting this and to Tim Peters for telling me about the registry hack to fix it.)


    Command Line Parameters

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

    $ EDIT Foo.txt

    What happens is that the operating system calls the program called EDIT and passes it the name of the file to edit, Foo.txt in this case. So 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 may also be some kind of magic variable (often called something like argc, for "argument count") 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'). Python doesn't need an argc type value since the usual len() method can be used to find the length of the list, and in most cases we don't even need that since we just iterate over the list using Python's for loop, like this:

    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>
    

    VBScript and JavaScript

    Being web page based the concept of command line arguments doesn't really arise. If we were using them within Microsoft's Windows Script Host environment the situation would be different, and WSH provides a mechanism to extract such arguments from a WshArguments object populated by WSH at run time.

    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. Of course GUI programs read input too and we will look more closely at how that's done much later in the tutorial.

    Points to remember
    • Use input() for reading strings.
    • input() can display a string to prompt the user.
    • EasyGui provides a GUI style mechanism equivalent to input() and print()
    • Command line arguments can be obtained from the argv list imported from the sys module in Python, where the first item is the name of the program.

    Previous  Next  Contents


    If you have any questions or feedback on this page send me mail at: alan.gauld@yahoo.co.uk