Kodomo

Пользователь

Учебная страница курса биоинформатики,
год поступления 2010

Файлы и Строки

Работа с файлами

Для начала, маленькое предисловие. В питоне (как и в подавляющем большинстве языков программирования) с файлами можно делать много разных операций: читать его построчно, читать его целиком, писать в него, двигать по нему курсор позиции, с которой мы будем читать или в которую мы будем писать...

Открытие файла.

В питоне каждый файл, с которым мы работаем, обозначается объектом. (А объект обозначается переменной).

Соответственно, прежде, чем с файлом начинать работать, нам нужно создать питонское представление об этом файле – создать объект, который представляет именно конкретный файл. В питоне эта операция называется "открыть файл". Делается это так:

   1 file = open('file.txt')

Такой файл можно только читать. Питон будет запрещать для него операции записи. Если нам нужно в файл писать, то мы пишем так:

   1 file = open('file.txt', "w")

Тут сразу предупреждаю: в тот момент, когда питон открывает файл на запись, если такой файл уже существовал, то он будет стёрт! Это свойство даже не столько питона, сколько большинства операционных систем. Его нужно всегда учитывать: нельзя указывать одинаковым входной и выходной файл для программы.

Что делать, если мы хотим дописать в файл? Для этого существуют еще один параметр 'a' (от 'append'):

   1 file = open('file.txt', "a") 

Путь к файлу указывается либо относительно текущей директории, либо относительно корневой директории (абсолютный путь):

   1 open("hello.txt") # открыть файл hello.txt в текущей директории
   2 
   3 # UNIX only:
   4 open("../task2/README") # открыть файл README, директорией выше в директории task2
   5 open("_darcs/prefs/author") # открыть файл author в поддиректории prefs в директории _darcs
   6 open("/bin/ls") # открыть файл ls в директории bin, лежащей в корневой директории /
   7 
   8 # Windows only:
   9 open("..\\Task2\\README")
  10 open("_darcs\\prefs\\author")
  11 open("H:\\Task3\\Python\\ls.py")

Так эти строки будут выглядять изнутри питона. Если имена файлов приходят из аргументов командной строки, то дублировать бэкслеши не надо. (В командной строке будет H:\Task3\Python – то, как FAR пишет пути, если ему щёлкнуть Ctrl-Enter по файлу).

Чтение по строкам

Если мы подставляем файл туда, где питон ожидал бы список, то питон будет интерпретировать файл как список строк файла – включая переносы в концах строк.

   1 for line in file:
   2         print line

Если мы распечатаем каждую строку таким образом, то в итоге на экране мы увидим все строки через пробел (пустую строку). Это произойдет из-за того, что в файле в конце каждой строки стоит символ '\n', а print автоматически прибавляет этот символ к концу печатаемого объекта. О решении этой проблемы поговорим чуть позже (см. Работа со строками и всякие полезные вещи при работе с файлами).

Чтение по байтам.

   1 bytes=file.read(1)

метод .read(1) возвращает строку bytes, в которой будет находиться 1 байт, прочитанный из файла.

Чтение целиком

Самым удобным способом чтения файла является его запись в 1 строку целиком с помощью метода .read():

   1 contents=file.read()

Запись в файл.

   1 file.write("Hello, file!\n")

дописывает одну строку в конец файла.

Обратите внимания: в отличие от print, эта функция переноса строки в конец не дописывает, нам приходится вставлять его туда самостоятельно!

StdIO

Существует три специальных потока, которые называются: стандартный поток ввода, стандартный поток вывода и стандартный поток ошибок.

Можно рассматривать каждую программу как некий универсальный переработчик, который имеет два разъёма: вход и выход. Эти вход и выход называются "стандартный вход" (stdin) и "стандартный выход" (stdout). Если мы у програмы никуда не привязываем выход, то, что из неё высыпается, сыпется на экран. А если не привязан вход, то она присасывается к клавиатуре и ловит всё, что вы набираете в консоли.

С точки зрения питона:

Стандартный вывод – это то, куда пишет print. Это такой файл. К нему можно дотянуться через sys.stdout.

Стандартный ввод – это то, чем мы пока что не пользовались. Это тоже такой файл. К нему можно дотянуться, как вы догадались, черзе sys.stdin.

Про стандартный поток ошибок - sys.stderr, это в общем то же самое, что stdout, только в него пишутся ошибки, а не содержательная выдача программы.

Работа со строками.

Итак, вернемся к чтению по строкам.

   1 for line in file:
   2         print line

Как уже было сказано, у нас возникает проблема с удвоением '\n'. Избавиться от этого лишнего пробельного символа можно с помощью метода strip().

.strip(): обрезание символов с концов строки

strip отрезает с начала и конца строки те символы, которые указаны в его аргументах (т.е. в скобках). Пустые скобки означают пробельные символы

   1 >>> a=" \t 1 2 "
   2 >>> a.strip()
   3 '1 2'

Важно! Строки, как и кортежи, нельзя изменить, поэтому при их любой обработке каким-то методом будет возвращаться новая строка!

То есть:

   1 >>> a=" \t 1 2 "
   2 >>> a.strip()
   3 '1 2'
   4 >>> a
   5 " \t 1 2 "

Если мы напишем:

   1 >>> a=a.strip()

то a изменит адрес, однако исходная строка останется прежней.

Еще примеры со strip:

   1 >>> '123abc231'.strip('12')
   2 '3abc23'

Как уже было сказано, strip обрезает с начала и конца строки все символы, которые указаны в его аргументах. Он работает только посимвольно! Поэтому с его помощью нельзя вырезать из строки '123abc231'число 12.

Вернемся к нашей проблеме. Метод strip() можно использовать, однако он удалит еще пробелы и в начале, что уже не есть хорошо. Чтобы избежать этого, надо указать в аргументах символ '\n', который обычно присутствует только в конце. Для полной уверенности можно использовать разновидность метода strip - rstrip, который вырезает символы с правого конца (аналогично, существует метод lstrip для левого). Тогда:

   1 for line in file:
   2     print line.rstrip('\n')

.split(): разбиение строки по заданным разделителям

Разбить строку на элементы списка можно с помощью метода .split()

   1 >>> " \t 1 2 ".split()
   2 ['1','2']  

В данном случае split() возвращает список, элементами которого являются слова, разделенные в исходной строке пробельными символами.

Ниже в примере _ означает пробел!

   1 >>> '1,_2,_3,4,_5'.split(',_') # в аргументе split указываем разделитель на элементы
   2 ['1','2','3,4','5']
   3 >>> a='1,_2,_3,4,_5'.split(',')
   4 ['1','_2','_3','4','_5']

split("строка") разбивает по строке, а не по символам, из которых она состоит!

split() при разбиении выкидывает пробелы в начале и в конце строки (смотри пример выше), а split(" ") нет!

   1 >>> " \t 1 2 ".split(' ')
   2 ['','\t','1','2','']

Есть два разделителя подряд – будет в списке пустая строка.

split(x,y): x - разделитель, y - вернуть первые y разбиений.

   1 >>>  ',,1,2,,3'.split(',',2)
   2 ['','','1,2,,3']
   3 >>>  '1'.split(',',2)
   4 ['1']

.join(): операция, обратная к split:

   1 >>>  line = 'a\t b \tc\t'
   2 >>>  fields = line.split("\t")
   3 >>>  "\t".join(fields)
   4 'a\t b \tc\t'

.replace()

   1 >>> "abcbd".replace("b", "x")
   2 "axcxd"
   3 >>> "abcbd".replace("b", "")
   4 "acd"

.lower(), .upper(): приведение строки к одному регистру

   1 >>> 'Ku-Ku'.lower()
   2 'ku-ku'
   3 >>> 'Ku-Ku'.upper()
   4 'KU-KU'
   5 >>> 'ku-KU'.capitalize()
   6 'Ku-ku'

.find(): поиск подстроки в строке

find(substring[, start[, end]])

Возвращает индекс первого вхождения подстроки в строку:

   1 >>> 'I like limes'.find('li')
   2 2

Можно также искать только в заданной подстроке исходной строки:

   1 >>> 'I like limes'.find('li',4)
   2 7

Если ничего не нашлось, возвращается -1:

   1 >>> 'I like limes'.find('li',4,7)
   2 -1
   3 startswith (prefix[, start[, end]])

Возвращает True, если строка начинается с данной подстроки:

   1 >>> 'I like limes'.startswith('I like')
   2 True

Так же, как и с find(), можно ограничивать подстроку в исходной строке:

   1 >>> 'I like limes'.startswith('like',2)
   2 True

Подстрока: string[start:end]

   1 >>> "abcbd"[1:-1]
   2 'bcb'

Параметры командной строки

Когда мы вызываем программу через командную строку, мы можем также указывать ее параметры (если они есть).

Например, вспомним команду ls. Ее можно вызвать с различными параметрами.

Все три записи выше равнозначны между собой.

Если параметр написан через знак дефиса, то он называется именованным, иначе – позиционным.

В переменной sys.argv содержится список строк - все то, что было написано в командной строке (разделенное по пробелам).

Например, если мы напишем маленькую программку test_argv.py:

   1 import sys
   2 print sys.argv

И запустим ее с какими-нибудь параметрами, то получится так:

$ python test_argv.py file.txt -r -w 5
['test_argv.py', 'file.txt', '-r', '-w', '5']