Python输入输出
There are several ways to present the output of a program; data can be printed in a human-readable form, or written to a file for future use. This chapter will discuss some of the possibilities.
这里有几种程序输出的展现方式;数据能够打印成人类可读的形式,或者被写入到文件中。这节我们将讨论这几个问题。
7.1. Fancier Output Formatting
So far we’ve encountered two ways of writing values: expression statements and the print() function. (A third way is using the write() method of file objects; the standard output file can be referenced as sys.stdout. See the Library Reference for more information on this.)
到目前为止,我们遇到了两种写值的方式:表达式语句和print()函数。(第三种方式是使用文件对象的write()方法;标准输出文件可以使用sys.stdout.可以参考Python库参考手册)
Often you’ll want more control over the formatting of your output than simply printing space-separated values. There are two ways to format your output; the first way is to do all the string handling yourself; using string slicing and concatenation operations you can create any layout you can imagine. The string type has some methods that perform useful operations for padding strings to a given column width; these will be discussed shortly. The second way is to use the str.format() method.
通常,你希望更多的控制输出的格式而不是简单的打印结果。有两种方式可以格式化你的输出,第一种方式是你自己处理所有的字符串,使用字符串的切片和连接操作你可以创造你希望的布局格式。字符串类型有很多方法来执行有用的操作,可以在给定的列宽度填充字符串,这些我们将会简短的讨论。第二种方式是使用str.format()方法。
The string module contains a Template class which offers yet another way to substitute values into strings.
string模块包含了一个Template类,该类提供了另一种方式替换值到字符串中。
One question remains, of course: how do you convert values to strings? Luckily, Python has ways to convert any value to a string: pass it to the repr() or str() functions.
还有一个问题,当然:怎么将值转换为字符串类型?幸运的是,Python有种方式可以将任何值转换为字符串:将该值传递个repr()或者str()方法。
The str() function is meant to return representations of values which are fairly human-readable, while repr() is meant to generate representations which can be read by the interpreter (or will force a SyntaxError if there is no equivalent syntax). For objects which don’t have a particular representation for human consumption, str() will return the same value as repr(). Many values, such as numbers or structures like lists and dictionaries, have the same representation using either function. Strings, in particular, have two distinct representations.
str()函数返回的字符串的值以更人性化的可读方式呈现,然而repr()函数是以解释器可读的形式呈现出来。对于许多值,其实str()和repr()函数的返回结果是相同的,例如数值或者列表,字典之类的结构。在特殊的情况下,字符串呈现的结果可能有差别,例如:
>>> s = 'Hello, world.' >>> str(s) 'Hello, world.' >>> repr(s) "'Hello, world.'" >>> str(1/7) '0.14285714285714285' >>> x = 10 * 3.25 >>> y = 200 * 200 >>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...' >>> print(s) The value of x is 32.5, and y is 40000... >>> # The repr() of a string adds string quotes and backslashes: ... hello = 'hello, world\n' >>> hellos = repr(hello) >>> print(hellos) 'hello, world\n' >>> # The argument to repr() may be any Python object: ... repr((x, y, ('spam', 'eggs'))) "(32.5, 40000, ('spam', 'eggs'))"
Here are two ways to write a table of squares and cubes:
下面的例子描述了写一个求正方形面积和体积的表格的两种方式:
>>> for x in range(1, 11): ... print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ') ... # Note use of 'end' on previous line ... print(repr(x*x*x).rjust(4)) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 >>> for x in range(1, 11): ... print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x)) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000
(Note that in the first example, one space between each column was added by the way print() works: it always adds spaces between its arguments.)
(注意,在第一个例子中,每列中间会增加一个空格,这个空格是print()函数自动增加的:print()函数默认就是在它的参数之间加一个空格)
This example demonstrates the str.rjust() method of string objects, which right-justifies a string in a field of a given width by padding it with spaces on the left. There are similar methods str.ljust() and str.center(). These methods do not write anything, they just return a new string. If the input string is too long, they don’t truncate it, but return it unchanged; this will mess up your column lay-out but that’s usually better than the alternative, which would be lying about a value. (If you really want truncation you can always add a slice operation, as in x.ljust(n)[:n].)
这个例子中表明字符串方法rjust(),它的功能是指定给定的宽度右对齐字符串,如果长度不够,则填充空格。这里也有相似的方法,例如:str.ljust()和str.center()。这些方法仅仅是返回一个格式化后的字符串。如果字符串太长,方法并不会截断字符串,而是直接返回该字符串,这可能会搅乱你的列对齐的方式,但通常是比较合适的方式相对于截断来说。
There is another method, str.zfill(), which pads a numeric string on the left with zeros. It understands about plus and minus signs:
这里有另一个方法str.zfill()。它会用0来填充数值字符串。而且可以自动识别加减号:
>>> '12'.zfill(5) '00012' >>> '-3.14'.zfill(7) '-003.14' >>> '3.14159265359'.zfill(5) '3.14159265359'
Basic usage of the str.format() method looks like this:
str.format()最基本的使用如下:
>>> print('We are the {} who say "{}!"'.format('knights', 'Ni')) We are the knights who say "Ni!"
The brackets and characters within them (called format fields) are replaced with the objects passed into the str.format() method. A number in the brackets can be used to refer to the position of the object passed into the str.format() method.
大括号中的内容会被format指定的列表依次替代。也可以在{}中指定format参数中的位置:
>>> print('{0} and {1}'.format('spam', 'eggs')) spam and eggs >>> print('{1} and {0}'.format('spam', 'eggs')) eggs and spam
If keyword arguments are used in the str.format() method, their values are referred to by using the name of the argument.
如果在str.format()函数中使用关键字参数,那么{}中必须指定参数的名字:
>>> print('This {food} is {adjective}.'.format( ... food='spam', adjective='absolutely horrible')) This spam is absolutely horrible.
Positional and keyword arguments can be arbitrarily combined:
位置传参合关键字参数能够任意组合:
>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred', other='Georg')) The story of Bill, Manfred, and Georg.
'!a' (apply ascii()), '!s' (apply str()) and '!r' (apply repr()) can be used to convert the value before it is formatted:
'!a'(相当于ascii()),'!s'(相当于str())'!r'(相当于repr())可以在格式化之前转换值的输出形式:
>>> import math >>> print('The value of PI is approximately {}.'.format(math.pi)) The value of PI is approximately 3.14159265359. >>> print('The value of PI is approximately {!r}.'.format(math.pi)) The value of PI is approximately 3.141592653589793.
An optional ':' and format specifier can follow the field name. This allows greater control over how the value is formatted. The following example rounds Pi to three places after the decimal.
一个冒号和指定的格式可以紧跟在字段名后(下面例子中的0就是代表字段名)。这极大的控制了值的格式化输出。下面这个例子格式化的输出PI:
>>> import math >>> print('The value of PI is approximately {0:.3f}.'.format(math.pi)) The value of PI is approximately 3.142.
Passing an integer after the ':' will cause that field to be a minimum number of characters wide. This is useful for making tables pretty.
在冒号的后面传递一个数值指明这个列的最小字符宽度是多少。下面这个例子显示了非常漂亮的表格:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678} >>> for name, phone in table.items(): ... print('{0:10} ==> {1:10d}'.format(name, phone)) ... Jack ==> 4098 Dcab ==> 7678 Sjoerd ==> 4127
If you have a really long format string that you don’t want to split up, it would be nice if you could reference the variables to be formatted by name instead of by position. This can be done by simply passing the dict and using square brackets '[]' to access the keys
如果你想要一个很长的格式化字符串,但是又不想分隔他们,你可以通过名字来引用格式化的变量。这仅仅只需要传一个字典参数,并使用方括号[]访问键值。(下面的0表示变量table,d表示int类型,也可以使e表示指数格式,当然也可以是1,2,3这些数值,表示宽度)
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; ' ... 'Dcab: {0[Dcab]:d}'.format(table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678
This could also be done by passing the table as keyword arguments with the ‘**’ notation.
也可以传递关键字参数,使用**标记符:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)) Jack: 4098; Sjoerd: 4127; Dcab: 8637678
This is particularly useful in combination with the built-in function vars(), which returns a dictionary containing all local variables.
结合内置函数vars(),这将变得非常有用。vars()函数返回一个字典类型,该字典包含所有本地变量。
For a complete overview of string formatting with str.format(), see Format String Syntax.
想要完全了解字符串的格式化通过str.format()函数,请查阅Format String Syntax。
7.1.1. Old string formatting
The % operator can also be used for string formatting. It interprets the left argument much like a sprintf()-style format string to be applied to the right argument, and returns the string resulting from this formatting operation. For example:
%也可以用于字符串的格式化,例如:
>>> import math >>> print('The value of PI is approximately %5.3f.' % math.pi) The value of PI is approximately 3.142.
7.2. Reading and Writing Files
open() returns a file object, and is most commonly used with two arguments: open(filename, mode).
open()函数返回一个文件对象,大多数情况下包含两个参数:open(filename,mode)。
>>> f = open('workfile', 'w')
The first argument is a string containing the filename. The second argument is another string containing a few characters describing the way in which the file will be used. mode can be 'r' when the file will only be read, 'w' for only writing (an existing file with the same name will be erased), and 'a' opens the file for appending; any data written to the file is automatically added to the end. 'r+' opens the file for both reading and writing. The mode argument is optional; 'r' will be assumed if it’s omitted.
第一个参数指定文件名,第二个参数指定文件的使用方式,‘r' 只读 'w'只写 'a' 在文件末尾写,'r+'读写,其实这些和C语言的fopen相一致的。
Normally, files are opened in text mode, that means, you read and write strings from and to the file, which are encoded in a specific encoding (the default being UTF-8). 'b' appended to the mode opens the file in binary mode: now the data is read and written in the form of bytes objects. This mode should be used for all files that don’t contain text.
正常情况下,文件是以文本模式打开的,这意味着你读写文件的编码默认是UTF-8。 'b'表示以二进制模式打开:这个时候文件是通过字节读写的。如果所有的文件都不包含文本字符串,则应该使用这种模式。
In text mode, the default when reading is to convert platform-specific line endings (\n on Unix, \r\n on Windows) to just \n. When writing in text mode, the default is to convert occurrences of \n back to platform-specific line endings. This behind-the-scenes modification to file data is fine for text files, but will corrupt binary data like that in JPEG or EXE files. Be very careful to use binary mode when reading and writing such files.
在文本模式下,不同的系统平台换行符是不同的(Unix平台下是\n,Windows平台下是\r\n),Python默认是\n。当在文本模式下进行写操作时,Python会自动将默认的换行符\n转换为平台对应的换行符。这种背后的转换对于文本文件是非常合适的,但是对于二进制数据,例如JPEG或者EXE文件则有弊端。因此当你使用二进制模式时,请小心对这类文件的读写。
7.2.1. Methods of File Objects
The rest of the examples in this section will assume that a file object called f has already been created.
后面的例子都假设文件对象f已经被创建了。
To read a file’s contents, call f.read(size), which reads some quantity of data and returns it as a string or bytes object. size is an optional numeric argument. When size is omitted or negative, the entire contents of the file will be read and returned; it’s your problem if the file is twice as large as your machine’s memory. Otherwise, at most size bytes are read and returned. If the end of the file has been reached, f.read() will return an empty string ('').
想读取文件内容,调用f.read(size),从文件中读取数据并返回字符串或字节对象。size是一个可选的参数。当省略size或者size为负数,整个文件将会被读取然后返回; 如果文件大小大于你机器内存的2被,将会出现问题。当指定size后,则读取指定的size大小并返回。当读取达到文件尾,f.read()将返回空字符串('')。
>>> f.read() 'This is the entire file.\n' >>> f.read() ''
f.readline() reads a single line from the file; a newline character (\n) is left at the end of the string, and is only omitted on the last line of the file if the file doesn’t end in a newline. This makes the return value unambiguous; if f.readline() returns an empty string, the end of the file has been reached, while a blank line is represented by '\n', a string containing only a single newline.
f.readline()读取一行;并且在读取的字符串末尾自动加\n。如果文件不是以另一行结尾,则省略'\n'。这使得返回值非常明确;如果f.readline()返回一个空字符串,则表示已经到达文件尾。如果f.readline()仅返回'\n',则说明读取了一个空行。
>>> f.readline() 'This is the first line of the file.\n' >>> f.readline() 'Second line of the file\n' >>> f.readline() ''
For reading lines from a file, you can loop over the file object. This is memory efficient, fast, and leads to simple code:
从文件中读取每一行,可以遍历文件对象。这是非常高效、快速的,并且代码很少:
>>> for line in f: ... print(line, end='') ... This is the first line of the file. Second line of the file
If you want to read all the lines of a file in a list you can also use list(f) or f.readlines().
如果你想读取所有的行到一个列表中,你可以使用list(f)或者f.readlines()。
f.write(string) writes the contents of string to the file, returning the number of characters written.
f.write(string)往文件中写入字符串,并返回写入的字符个数。
>>> f.write('This is a test\n') 15
To write something other than a string, it needs to be converted to a string first:
如果想写入其他类型的值,首先需要转换为字符串类型:
>>> value = ('the answer', 42) >>> s = str(value) >>> f.write(s) 18
f.tell() returns an integer giving the file object’s current position in the file represented as number of bytes from the beginning of the file when in binary mode and an opaque number when in text mode.
f.tell()返回一个整数值,这个整数值表示文件对象当前在文件中的位置。如果是文本文件,该位置代表从文件头到该位置的字符数。但是如果在二进制模式下,这个值是个未确定值。
To change the file object’s position, use f.seek(offset, from_what). The position is computed from adding offset to a reference point; the reference point is selected by the from_what argument. A from_what value of 0 measures from the beginning of the file, 1 uses the current file position, and 2 uses the end of the file as the reference point. from_what can be omitted and defaults to 0, using the beginning of the file as the reference point.
要改变文件对象的位置,可以使用f.seek(offset,from_what)函数。offset表示当前文件对象位置到引用点的偏移,这个引用点通过from_what指定。from_what等于0表示从引用点就是文件开头,1表示当前文件位置,2表示文件尾。from_what可以省略,默认为0,使用文件开头作为引用点。
>>> f = open('workfile', 'rb+') >>> f.write(b'0123456789abcdef') 16 >>> f.seek(5) # Go to the 6th byte in the file 5 >>> f.read(1) b'5' >>> f.seek(-3, 2) # Go to the 3rd byte before the end 13 >>> f.read(1) b'd'
In text files (those opened without a b in the mode string), only seeks relative to the beginning of the file are allowed (the exception being seeking to the very file end with seek(0, 2)) and the only valid offset values are those returned from the f.tell(), or zero. Any other offset value produces undefined behaviour.
在文本文件中,
When you’re done with a file, call f.close() to close it and free up any system resources taken up by the open file. After calling f.close(), attempts to use the file object will automatically fail.
当你使用完文件后,调用f.close()关闭它,是否该文件拥有的系统资源。当调用f.close()之后,如果还要使用文件对象,则会失败。
>>> f.close() >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: I/O operation on closed file
It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way. It is also much shorter than writing equivalent try-finally blocks:
使用with关键字处理文件对象是最佳的实践。这个优点在于:当文件操作完成后,文件会在适当的时候自动关闭,既使操作文件的过程中发生了异常。这总比try-finally块要简短多。
>>> with open('workfile', 'r') as f: ... read_data = f.read() >>> f.closed True
File objects have some additional methods, such as isatty() and truncate() which are less frequently used; consult the Library Reference for a complete guide to file objects.
文件对象也有其他的一些方法:例如isatty(),truncate(),这些函数比较少使用。详情请查阅Python库参考手册。
7.2.2. Saving structured data with json
Strings can easily be written to and read from a file. Numbers take a bit more effort, since the read() method only returns strings, which will have to be passed to a function like int(), which takes a string like '123' and returns its numeric value 123. When you want to save more complex data types like nested lists and dictionaries, parsing and serializing by hand becomes complicated.
字符串可以很容易的用于文件的读写。数值可能需要转换一下,因为read()方法只能返回字符串,这也可以通过int()函数进行转换,例如read返回'123',然后转换为数值123.当你希望保存更复杂的数据类型,例如嵌套的列表和字典,手动分析起来或序列化会变得很复杂。
Rather than having users constantly writing and debugging code to save complicated data types to files, Python allows you to use the popular data interchange format called JSON (JavaScript Object Notation). The standard module called json can take Python data hierarchies, and convert them to string representations; this process is called serializing. Reconstructing the data from the string representation is called deserializing. Between serializing and deserializing, the string representing the object may have been stored in a file or data, or sent over a network connection to some distant machine.
与其使用户不断的通过编写和调试代码来保存复杂的数据类型到文件中,Python允许你使用流行的数据转换格式:JSON(JavaScript Object Notation)。这个标准模块叫json,使Python数据分层,并转换为字符串形式;这种处理过程叫做序列化。从字符串到还原原来的数据结构的过程叫做反序列化。在序列化和反序列化的过程中,字符串形式的对象可以被存储到文件中,或者通过网络发送到远程机器上。
If you have an object x, you can view its JSON string representation with a simple line of code:
如果你有一个对象x,你可以看到它的JSON字符串形式,通过下面一行简单的代码:
>>> json.dumps([1, 'simple', 'list']) '[1, "simple", "list"]'
Another variant of the dumps() function, called dump(), simply serializes the object to a text file. So if f is a text file object opened for writing, we can do this:
dumps()函数的另一个变体:dump(),简单的序列化对象存储到文本文件中,因此,如果f是一个文本文件对象,我们可以这样:
json.dump(x, f)
To decode the object again, if f is a text file object which has been opened for reading:
要还原x对象,可以这样读取:
x = json.load(f)
This simple serialization technique can handle lists and dictionaries, but serializing arbitrary class instances in JSON requires a bit of extra effort. The reference for the json module contains an explanation of this.
这种简单的序列化技术能够处理列表和字典类型,但是用JSON序列化任意的对象实例需要一些额外的代价。
原文链接:https://docs.python.org/3.4/tutorial/inputoutput.html#fancier-output-formatting