© Paul Gerrard 2016
Paul GerrardLean Python10.1007/978-1-4842-2385-7_4

4. Input and Output

Paul Gerrard
(1)
Maidenhead, Berkshire, UK
 
If a program did not produce any output, it wouldn’t be very useful, would it? If a program did not accept some data that varied from time to time, it would produce the same result again and again and again, and that wouldn’t be very useful either (after its first run at least). Most programs, therefore, need to accept some inputs or input data, so that they can product output data, outputs, or results.
In this chapter, we cover three important input/output mechanisms:
  • Displayed output.
  • Getting data from the user through the keyboard.
  • Getting input from and writing output to disk files.

Displaying Output

You’ve seen the print () function1 quite a few times already. The most common way of getting output from a program is to use the print() statement. Print is a function that takes as its arguments the items to be displayed. Optionally, you can also define a separator that is placed between the displayed items and a line terminator value that can replace a newline. The function call looks like this:
print(arg1,arg2,arg3...,sep=' ',end='\n')
Here are some examples of the print() function in use.
>>> boy="Jack"
>>> girl="Jill"
>>> print("Hello World!")
Hello World!
>>> print(boy,'and',girl,'went up the hill')
Jack and Jill went up the hill
It is common to use the string formatting feature.
>>> print('%d plus %d makes %d' % (3, 7, 10))
3 plus 7 makes 10
You can suppress the trailing newline by setting the end argument to an empty string (or something else).
>>> #
>>> # the end= argument defaults to '\n'
>>> # if you change it, there won't be a newline
>>> #
>>> print('one...','two...','three',end='')
one... two... three>>>    # note the >>> prompt
The string separator defaults to a single space but can be changed or suppressed by setting it to an empty string.
>>> #
>>> # the sep= argument defaults to a space ' '
>>> # but you can change it, for example...
>>> #
>>> print('one...','two...','three',sep='***')
one...***two...***three

Getting User Input

The easiest way to get data into the program is to use the input () 2 function. It takes one argument, which is the prompt you see displayed on the command line. The function returns a string value, so if you are asking for numeric or multiple values separated by commas, you will have to parse and process the text in the code before the data can be used.
>>> yourName=input('Enter your name: ')
Enter your name: Paul
>>> print('Your name is',yourName)
Your name is Paul
If you ask the user for an integer number, you should check that the entered text is valid and can be converted to an integer. To do this, you might do the following:
  • Use len(text) to verify that some text has been entered.
  • Use the string function text.isdigit() to check the text represents a number.
  • Use the int(text) to convert the text to an integer so you can process it.
You might have heard of the “garbage-in, garbage-out” concept. If you don’t validate the data coming into your program, its behavior might be unpredictable or it might fail or just produce strange results. Don’t forget that hackers can exploit poor input validation to cause mayhem on Internet sites.
Note
It is your responsibility, as programmer, to ensure that only data that meets your validation rules is accepted by your program.

Writing and Reading Files

At one point or another, you are going to have to read and write text files on disks or other devices. We look specifically here at text-only files and how you can access them.

Opening Files

To access a file on disk you create a file object and you use the open() function to do this. The format of the open call is:
fileobj = open(filename,mode)
The named file would normally be opened in the current directory, but the name can include a path so it can open any file on any disk and in any directory (local permissions allowing). The mode tells the interpreter to open the file for reading 'r', writing 'w', or appending 'a'.
Table 4-1 shows the outcomes of opening existing and nonexistent files with the three mode values.
Table 4-1.
Opening Files with the Three Mode Values
Open Mode
File Exists
File Does Not Exist
'r'
Open for reading
No such file or directory error
'w'
Overwritten by empty file and open for writing
Open for writing
'a'
Open for appending
New empty file created and open for writing
Note
Be careful when using the write mode; you might overwrite a file containing valuable data and lose it.
Here are some examples of how to open files:
fname='myfile.txt'
fp = open(fname,'r')  # open for reading (must exist)
fp = open(fname,'w')  # creates new file for writing
fp = open(fname,'a')  # opens file for appending

Closing Files

Once you have finished reading from or writing to a file, it is a good idea to close it using the close () function.
fp = open(fname,'w')  # open for writing
#
# do some writing, etc.
#
fp.close()
If you don’t explicitly close files, you shouldn’t encounter any major problem, but it is always best to pair open() and close() functions for the sake of completeness and tidiness.

Reading Files

The standard function to read data from a file is read() . It reads the entire contents of the file into a string variable. The content can then be split into separate lines delimited by the newline character ('\n').
fp = open(fname,'r')  # open for reading
text = fp.read()
lines=text.split('\n')
fp.close()
A more common way to read a file into memory is readlines() , which returns a list containing each line.
fp = open(fname,'r')  # open for reading
lines = fp.readlines()
fp.close()
Every entry in the lines list just shown will have a newline at its end, so a good way of cleaning up the readlines() data would be to use a list comprehension:
lines = [line.rstrip() for line in fp.readlines()]
If you want to read a file line by line, the best way is to make use of the fact that the file object itself returns an iterator like this:
fp = open(fname,'r')  # open for reading
for eachLine in fp:
  #
  # process each line in turn
  #
  print(eachLine,end='')  # suppress the extra \n
fp.close()
Note
Whichever way you read a file, the text that is read contains the trailing newline character; you must remove it yourself.

Writing to Files

The standard function to write data to a file is write() , which works exactly as you would expect.
fp.write(textline)
Note that the write() function does not append a newline to the text before writing. Here is a simple example:
fp = open('text.txt','w')
while True:
    text = input('Enter text (end with blank):')
    if len(text)==0:
        break
    else:
        fp.write(text+'\n')
fp.close()
If you didn’t add the trailing '\n' newline in the write statement, all the lines of text would be merged into a single long string. If you have a list of strings, you can write the list out as a file in one statement, but you must remember to append a newline to each string to make the file appear as you expect.
Here are two ways of writing out a list to a file:
lines=['line 1','line 2','line 3','line 4']
# write all lines with no '\n'
fp.writelines(lines)
# writes all line with '\n'
fp.writelines([line+'\n' for line in lines])
Note
The write() and writelines() functions do not append trailing newline (\n) characters; you must do that yourself.

Accessing the File System

There are a number of useful file system functions. They are all available using the os module, which you must import.
import os
# remove a file (deleteme.txt) from disk
os.unlink('deleteme.txt')   
# rename file on disk (from file.txt to newname.txt)
os.rename('file.txt','newname.txt')
# change current/working directory
os.chdir(newdirectory)
# create list of files in a directory
filelist = os.listdir(dirname)
# obtain current directory
curdir = os.getcwd()
# create a directory
os.mkdir(dirname)
# remove a directory (requires it to be empty)
os.rmdir(dirname)
# in the following examples, we need to use
# the os.path module
#
# does the file/directory exist?
exists = os.path.exists(path)
# does path name exist and is it a file?
isfile = os.path.isfile(filepathname)
# does path name exist and is it is directory?
isdir = os.path.isdir(filepath)

Command-Line Arguments

The input() function allows you to get input from the user using the keyboard at any point in your program. Often, though, it is more convenient to the user to provide input directly after the program name in a command line. Most command-line utilities have options and data to be used in its process; for example:
python mycopy.py thisfile.txt thatfile.txt
This might be a program that makes a copy of one file to another.
The arguments are captured in the sys.argv list from the sys module. Here is some code that demonstrates how to capture the command-line arguments (command.py):
import sys
nargs=len(sys.argv)
print('%d argument(s)' % (nargs))
n=0
for a in sys.argv:
    print('  arg %d is %s' % (n,a))
    n+=1
Let’s try running our program with three arguments:
D:\LeanPython>python command.py arg1 arg2 arg3
4 argument(s)
  arg 0 is command.py
  arg 1 is arg1
  arg 2 is arg2
  arg 3 is arg3
Note that the first (element 0) argument is always the name of the program itself.
Footnotes
1
Note that in Version 2, print was a statement, not a function, so it behaves differently. Print() is a common Version 3 stumbling block so take a look at https://docs.python.org/3/whatsnew/3.0.html .
 
2
In Version 2, Python uses the function raw_input() instead. It works exactly like the input() function in Version 3.