В Python все операции ввода-вывода заключены в API высокого уровня: файлу нравятся объекты.
Это означает, что любой объект, которому нравится файл, будет вести себя одинаково и может использоваться в ожидающей их функции. Это называется утиной печатью, и для файловоподобных объектов можно ожидать следующее поведение:
- открыть / закрыть / исключения IO
- итерация
- 1010 * буферизация *
- чтение / письмо / поиск
StringIO, File и все подобные объектам файлы действительно могут быть заменены друг на друга, и вам не нужно заботиться об управлении вводом-выводом самостоятельно.
В качестве небольшой демонстрации давайте посмотрим, что вы можете сделать со стандартным выводом stdout, который представляет собой файл в виде объекта:
import sys
# replace the standar ouput by a real opened file
sys.stdout = open("out.txt", "w")
# printing won't print anything, it will write in the file
print "test"
Все файловые объекты ведут себя одинаково, и вы должны использовать их одинаково:
# try to open it
# do not bother with checking wheter stream is available or not
try :
stream = open("file.txt", "w")
except IOError :
# if it doesn't work, too bad !
# this error is the same for stringIO, file, etc
# use it and your code get hightly flexible !
pass
else :
stream.write("yeah !")
stream.close()
# in python 3, you'd do the same using context :
with open("file2.txt", "w") as stream :
stream.write("yeah !")
# the rest is taken care automatically
Обратите внимание, что методы, подобные объектам типа файла, имеют общее поведение, но способ создания объекта, подобного файлу, не является стандартным:
import urllib
# urllib doesn't use "open" and doesn't raises only IOError exceptions
stream = urllib.urlopen("www.google.com")
# but this is a file like object and you can rely on that :
for line in steam :
print line
В прошлом мире это не потому, что он работает так же, как и основное поведение. Важно понимать, с чем вы работаете. В последнем примере использование цикла for для интернет-ресурса очень опасно. В самом деле, вы знаете, что у вас не будет бесконечного потока данных.
В этом случае используйте:
print steam.read(10000) # another file like object method
безопаснее. Высокие абстракции являются мощными, но не избавляют вас от необходимости знать, как все это работает.