Additional notes on I/O#

At this point, we already acquired the basic skills to write a working Python code. An important part of the code is reading external data and writing results. We already learned the basics on Input/Output and, in this chapter, we give a closer look on how to print messages and results to the screen and files with a proper format.

The print function#

The central function for printing in Python is print. It can be used to print a single variable (of any kind) or a sequence of variables.

print('Hello world!', 1.5, True, [1, 2, 3], sep=' | ', end='\n--\n')

Some keyword arguments can be used to modify the output. For example, we can specify the character(s) at the end of the line with the end keyword. The default value is the newline character \n (new line), so if we use end='' we will get subsequent statements printed in the same line. Another keyword that tune the output is sep, which specifies the string use as separator between variables (if a sequence of variables is given). The default value is a space.

Another important keyword is file, which specifies the output stream. The argument must be a file object, usually generated with the open function. Note that the file should be writable (i.e., using the keyword w on opening). The default value is sys.stdout, which is the standard output stream.

Before closing this section, we will look at an alternative way to print variables, i.e., through the write method of file objects. One of the main differences with the print function is that the write method does not add a newline character at the end.

# Set file object to standard output
f = sys.stdout

# With write method
f.write('Hello world!\n')

# With print function
print('Hello world!', file=f)

Formatting your output#

Note that while we can print any variable with the print function it does not allow us to specify the format of the output (e.g., specify the number of decimals for a float). To do this, we need to generate a string that will contain the variables with the desired format. We then pass such a string to the print function.

There are three ways to generate a string with variables:

  • format method of the string.

  • f-strings (formatted strings, since Python 3.6).

  • String modulo operator (%).

In the two first cases, the string is a template that contains placeholders for the variables identified by curly braces {}. The more general syntax is {<variableID>:<format>}. The way <variableID> is specified depends on the method used to generate the string. Namely, the format() function contains the variables as arguments, and <variableID> is the position of the variable in the argument list. If no identifier is used, the variables are used in the order they appear in the argument list. The f-strings are defined with the f modifier, i.e., f"my_string". They are a bit more flexible, and allow to directly use a variable, or any valid Python expression as <variableID>.

The third method uses the % character as placeholder within the string, with syntax %<format>, where in this case <format> must be specified. The variables to substitute are given after the string, using a tuple if more than one is given.

# Using the format method
print('The value of x is {} and the value of y is {}'.format(x, y))

# Using f-strings
print(f'The value of x is {x} and the value of y is {y}')

# Using string modulo operator (%)
print('The value of x is % and the value of y is %' % (x, y))

The <format> field is a string that specifies the format of the variable, with details such as the total width, the number of decimals or the alignment. The most common syntax is <align>W<type>, where <align> is the alignment (not available with % method, and optional with the other two), W is the total width (and may also include the number of positions after the period for floats as W.n), and <type> is the format type. The most common types are:

  • s: string (actually not necessary to specify, since it is the default)

  • d: integer (again, not necessary)

  • f: float in decimal format

  • e: float in scientific notation

  • g: float in scientific notation or decimal format, or integer, depending on the value

The alignment can be specified with the <align> part of the format, and the most usual options are: < (left aligned), > (right aligned), and ^ (centered). The default is left alignment for strings, and right alignment for numbers.

Let’s take a look to the outcome of different formats for the same variables.

x,y = 1,2
print(f'The value of x is {x:<10d} and the value of y is {y:<10}')
print(f'The value of x is {x:^10.2f} and the value of y is {y:^10.2e}')
print(f'The value of x is {x:>10.2g} and the value of y is {y:>10.2e}')
The value of x is 1          and the value of y is 2         
The value of x is    1.00    and the value of y is  2.00e+00 
The value of x is          1 and the value of y is   2.00e+00

Using specific libraries for I/O#

Through this chapter, we have seen how to read and write files using some python built-in functions. However, in many cases, you will find that, while working with specific file formats, some libraries will do this task more conveniently. For example, arrays can be read/written with NumPy’s specific functions, molecular structure with the IO module of ASE and data frames can be read and written with Pandas. You will see some examples of these libraries in the corresponding chapters.