# Файлы Python
## чтение и запись файлов в Python
### Открытие файлов в Python
Python имеет встроенную **open()** функцию для открытия файла. Эта функция возвращает файловый объект, также называемый дескриптором, поскольку он используется для чтения или изменения файла соответствующим образом.
```
f = open("test.txt") # открыть файл в текущей директории
f = open("C:/Python38/README.txt") # полный путь до открываемого файла
```
Мы можем указать режим при открытии файла. В режиме мы указываем, хотим ли мы **читать** **r**, **писать** **w** или **добавлять** **a** в файл. Мы также можем указать, хотим ли мы открыть файл в текстовом или двоичном режиме.
**По умолчанию чтение в текстовом режиме**. В этом режиме мы получаем строки при чтении из файла.
С другой стороны, двоичный режим возвращает байты, и этот режим следует использовать при работе с нетекстовыми файлами, такими как изображения или исполняемые файлы.
- r - Открывает файл для чтения. (По умолчанию)
- w - Открывает файл для записи. Создает новый файл, если он не существует, или усекает файл, если он существует.
- x - Открывает файл для монопольного создания. Если файл уже существует, операция завершится ошибкой.
- a - Открывает файл для добавления в конец файла без его усечения. Создает новый файл, если он не существует.
- t - Открывается в текстовом режиме. (По умолчанию)
- b - Открывается в бинарном режиме.
- "+" - Открывает файл для обновления (чтения и записи)
```
f = open("test.txt") # режим по умолчанию чтения 'r' или 'rt'
f = open("test.txt",'w') # режим записи
f = open("img.bmp",'r+b') # чтение и запись в бинарном режиме
f = open("test.txt", mode='r', encoding='utf-8') # указан тип кодироки
```
### Закрытие файлов в Python
Это делается с помощью **close()** метода.
Лучший способ закрыть файл — использовать **with оператор**. Это гарантирует, что файл будет закрыт при выходе из блока внутри withоператора.
Нам не нужно явно вызывать close() метод. Это делается внутри.
```
with open("baz.txt") as f:
s = f.read() # все что внутри будет закрыто после выхода из этого блока
print()
print("end")
```
### Запись в файлы в Python
Чтобы записать в файл в Python, нам нужно открыть его **в режиме записи w**
```
with open("test.txt",'w',encoding = 'utf-8') as f:
f.write("my first file\n")
f.write("This file\n\n")
f.write("contains three lines\n")
```
Эта программа создаст новый файл с именем test.txt в текущем каталоге, если он не существует. Если он существует, он перезаписывается.
Мы должны сами включать символы новой строки, чтобы различать разные строки.
### Чтение файлов в Python
**МЕТОД read()**
Чтобы прочитать файл в Python, мы должны открыть файл в **r режиме чтени**. При использовании метода **read()** он возвращает новую строку как '\n'. Как только конец файла достигнут, мы получаем пустую строку при дальнейшем чтении
```
s = f.read(7) # первые 7 символов читается
print(s.encode()) # видим символы типо переноса строки
```
Мы можем изменить наш текущий файловый курсор (положение), используя **seek()** метод. Точно так же **tell()** метод возвращает нашу текущую позицию (в количестве байтов).
```
f.tell() # возвращаем текущую позицию в файле
56
f.seek(5) # задаем сдвиг на который хотим перенести указатель чтения
0
```
Мы можем читать файл построчно, используя цикл for . Это и эффективно, и быстро.
```
for line in f:
print(line, end = '')
This is my first file
This file
contains three lines
```
**МЕТОД readline()**
Этот метод читает файл до новой строки, включая символ новой строки.
```
f = open("foo.txt") # в режими чтения, по умолчанию
s1 = f.readline() # one two three\n (вычитал всю строку включая \n) ЧИТАЕТ ПОСТРОЧНО
s2 = f.readline()
s3 = f.readline()
print(s1) # добавляет символ новый строки таким образом в итоге у нас будет два \n
print(s2.strip()) # методом стрип обрезаем второй перенос на новую строку
print(s3.strip())
f.close()
```
**МЕТОД readlines()**
```
f = open("foo.txt") # в режими чтения, по умолчанию
# способ для гигантских файлов
s = f.readlines(32) # возвращает список состоящий из всех строк файла (вычитывает строку до конца и добавляет ее в список)
print(s)
```
## Управление каталогами и файлами
В Python есть **os модуль**, который предоставляет нам множество полезных методов для работы с каталогами(а также с файлами).
### Получить текущий каталог
Мы можем получить текущий рабочий каталог, используя **getcwd()** метод osмодуля.
Этот метод возвращает текущий рабочий каталог в виде строки. Мы также можем использовать **getcwdb(**) метод, чтобы получить его как объект байтов.
```
import os
os.getcwd()
'C:\\Program Files\\PyScripter'
os.getcwdb()
b'C:\\Program Files\\PyScripter'
```
Дополнительная обратная косая черта подразумевает escape-последовательность. Функция **print()** отобразит это правильно.
```
print(os.getcwd())
C:\Program Files\PyScripter
```
### Изменение каталога
Мы можем изменить текущий рабочий каталог, используя **chdir()** метод.
Новый путь, который мы хотим изменить, должен быть предоставлен этому методу в виде строки. Мы можем использовать как прямую, так **/** и обратную косую черту **\** для разделения элементов пути.
При использовании обратной косой черты безопаснее использовать управляющую последовательность.
```
os.chdir('C:\\Python33')
print(os.getcwd())
C:\Python33
```
### Список каталогов и файлов
Все файлы и подкаталоги внутри каталога могут быть получены с помощью **listdir()** метода.
Этот метод принимает путь и возвращает список подкаталогов и файлов по этому пути. Если путь не указан, возвращается список подкаталогов и файлов из текущего рабочего каталога.
```
print(os.getcwd())
C:\Python33
os.listdir()
['DLLs',
'Doc',
'include',
'Lib',
'libs',
'LICENSE.txt',
'NEWS.txt',
'python.exe',
'pythonw.exe',
'README.txt',
'Scripts',
'tcl',
'Tools']
os.listdir('G:\\')
['$RECYCLE.BIN',
'Movies',
'Music',
'Photos',
'Series',
'System Volume Information']
```
### Создание нового каталога
Мы можем создать новый каталог, используя **mkdir()** метод.
Этот метод принимает путь к новому каталогу. Если полный путь не указан, новый каталог создается в текущем рабочем каталоге.
```
os.mkdir('test')
os.listdir()
['test']
```
### Переименование каталога или файла
Метод **rename()** может переименовать каталог или файл.
Для переименования любого каталога или файла rename() метод принимает два основных аргумента: старое имя в качестве первого аргумента и новое имя в качестве второго аргумента
```
os.listdir()
['test']
os.rename('test','new_one')
os.listdir()
['new_one']
```
### Удаление каталога или файла
```
os.listdir()
['new_one', 'old.txt']
os.remove('old.txt')
os.listdir()
['new_one']
os.rmdir('new_one')
os.listdir()
[]
```
-------------
#### *rmdir() метод может удалять только пустые каталоги!!!*
-------------
Чтобы удалить непустой каталог, мы можем использовать **rmtree() метод** внутри **shutil модуля**
```
os.listdir()
['test']
os.rmdir('test')
Traceback (most recent call last):
...
OSError: [WinError 145] The directory is not empty: 'test'
import shutil
shutil.rmtree('test')
os.listdir()
[]
```