{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Программирование для дата-журналистики\n", "\n", "\n", "## Конспект лекции о работе с файлами и путями к ним\n", "\n", "- Лекция: И. Щуров\n", "- Текст: А. Щёнников\n", "- [Страница курса](http://math-info.hse.ru/s18/k)\n", "\n", "\n", "\n", "Мы будем работать с функциями для работы с операционной системой, для этого нам нужно импортировать модуль **os**." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import os" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Функция `getcwd()` (get current work directory) — возвращает *абсолютный* путь к текущей рабочей директории/каталогу/папке. Это далеко не обязательно та директория в которой находится запущенный .ipynb файл.\n", "В зависимости от операционной системы путь может выглядеть по-разному:\n", "\n", " \"/disk/user/dir\" — под Mac/Linux\n", " \"D:\\\\user\\\\dir\" — под Windows (в целом, современные версии понимают написание не через обратный слеш)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "os.getcwd()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Так, например, если в текущем рабочем каталоге будет находиться файл \"myfile.txt\", то мы сможем открыть его указав лишь его имя. \n", "Но абсолютный путь к файлу будет выглядеть как:\n", "\n", " \"/disk/user/dir/myfile.txt\"\n", " или\n", " \"D:\\\\disk\\user\\dir\\myfile.txt\"" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello!\n", "This is file with text.\n", "\n" ] } ], "source": [ "with open(\"myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Обратите внимание, что если вы хотите вручную прописать путь к файлу, а не только его имя, чтобы использовать в строке символ обратного слеша вам нужно написать его дважды _**\"\\\\\\\\\"**_, т.к. сам по себе знак _**\"\\\\\"**_ имеет особый смысл (например, используется для передачи специальных символов типа `\\n`)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "a\\b\n" ] } ], "source": [ "print(\"a\\\\b\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Задача" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Создайте любой файл в текущем рабочем каталоге\n", "# Откройте его, используя абсолютный путь, как в примере внизу" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello!\n", "This is file with text.\n", "\n" ] } ], "source": [ "with open(\"/Users/teacher/myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File in folder «My Nice Folder».\n", "\n" ] } ], "source": [ "with open(\"/Users/teacher/My Nice Folder/myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File in folder «My Nice Folder».\n", "\n" ] } ], "source": [ "with open(\"My Nice Folder/myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Текущий рабочий каталог можно поменять, используя функцию **os.chdir()**. Ваш .ipynb файл при этом останется на прежнем месте, измениться лишь точка отсчета для доступа к файлам." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "os.chdir('/Users/teacher')" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "os.chdir(\"My Nice Folder\")" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'/Users/teacher/My Nice Folder'" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.getcwd()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Будьте внимательны, при смене рабочего каталога вы не сможете открывать только по имени файлы, которые лежали в прежнем рабочем каталоге." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File in folder «My Nice Folder».\n", "\n" ] } ], "source": [ "with open(\"myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello!\n", "This is file with text.\n", "\n" ] } ], "source": [ "with open(\"/Users/teacher/myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Так же как и с файлами, если вам необходимо обратиться к каталогу, который лежит в текущем рабочем каталоге, вам достаточно просто написать его имя. Если же вы хотите обратиться к каталогу, *в котором* находится ваш текущий рабочий каталог, досаточно написать _**\"..\"**_.\n", "\n", "Например, наша файловая система выглядит следующим образом:\n", "\n", " disk/user/dir0/dir1/dir2\n", " \n", "Текущий рабочий каталог — **dir1**, нам необходимо обратиться к каталогу **dir2**, тогда достаточно написать _**\"dir2/\"**_. Если мы хотим попасть в каталог **dir0**, нужно написать _**\"../\"**_" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello!\n", "This is file with text.\n", "\n" ] } ], "source": [ "with open(\"../myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Путь, который строится относительно текущего рабочего каталога, называется _относительным_ путём." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Путь _**\"./\"**_ (одна точка) — это способ указать текущий рабочий каталог в виде строки." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File in folder «My Nice Folder».\n", "\n" ] } ], "source": [ "with open(\"./myfile.txt\") as f:\n", " print(f.read())" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "os.chdir(\"/Users/teacher\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Метод **os.listdir()** возвращает список всех объектов (и файлов и каталогов), которые содердатся в директории. В скобках можно указать путь к директории (в виде строки, например, `os.listdir(\"disk/user/dir0/dir1/dir2\")`) список объектов которой необходимо получить, по умолчанию функция возвращает список объектов текущего рабочего каталога." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['.adobe',\n", " '.anaconda',\n", " '.atom',\n", " '.bash_history',\n", " '.bash_profile',\n", " '.bash_sessions',\n", " '.cache',\n", " '.CFUserTextEncoding',\n", " '.conda',\n", " '.condarc',\n", " '.cups',\n", " '.DS_Store',\n", " '.gitconfig',\n", " '.ipynb_checkpoints',\n", " '.ipython',\n", " '.jupyter',\n", " '.local',\n", " '.oracle_jre_usage',\n", " '.spss',\n", " '.ssh',\n", " '.Trash',\n", " '.viminfo',\n", " 'anaconda3',\n", " 'Applications',\n", " 'Desktop',\n", " 'Documents',\n", " 'Downloads',\n", " 'electors.csv',\n", " 'large_states.txt',\n", " 'Library',\n", " 'Movies',\n", " 'Music',\n", " 'My Nice Folder',\n", " 'myfile.txt',\n", " 'newfile.txt',\n", " 'Pictures',\n", " 'Public',\n", " 'results.csv',\n", " 'test',\n", " 'test_work_xjz.ipynb',\n", " 'Untitled.ipynb',\n", " 'Untitled1.ipynb',\n", " 'Untitled2.ipynb',\n", " 'Untitled3.ipynb',\n", " 'Untitled4.ipynb']" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.listdir()" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['myfile.txt']" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.listdir(\"My Nice Folder/\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Файл в каталоге не всегда может иметь в конце названия привычное расширение в виде несколькоих знаков после точки (.txt/.csv). Чтобы определить является ли объект каталога файлом, а не каталогом, существует функция **os.path.isfile()**, которая на вход принимает путь к файлу в виде строки." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.path.isfile(\"results.csv\")" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.path.isfile(\"My Nice Folder\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Соответственно с помощью функции **os.path.isdir** можно проверить является ли объект директорией." ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.path.isdir(\"My Nice Folder\")" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ ".bash_history\n", ".bash_profile\n", ".CFUserTextEncoding\n", ".condarc\n", ".DS_Store\n", ".gitconfig\n", ".viminfo\n", "electors.csv\n", "large_states.txt\n", "myfile.txt\n", "newfile.txt\n", "results.csv\n", "test_work_xjz.ipynb\n", "Untitled.ipynb\n", "Untitled1.ipynb\n", "Untitled2.ipynb\n", "Untitled3.ipynb\n", "Untitled4.ipynb\n" ] } ], "source": [ "# Задача: вывести на экран все файлы в текущем каталоге (без подкаталогов)\n", "for filename in os.listdir():\n", " if os.path.isfile(filename):\n", " print(filename)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "По сути, как было указано выше, пути к файлам это обычные строки, и с ними можно производить обычные операции предусмотренные для строк. Например, если у нас в текущем рабочем каталоге есть каталог `\"dir2\"`, а в нем лежит файл _`\"file.txt\"` и мы работаем под Windows, то мы можем построить относительный путь к этому файлу так: `\"dir2\" + \"\\\\\" + \"file.txt\"`, и получим строку `\"dir2\\\\file.txt\"`. Но гораздо аккуратнее будет соединять отдельные части пути с помощью функции `os.path.join()`, которая на вход получает два или больше компонента пути и создаёт строку в том формате, который поддерживается операционной системой, на которой запущен код. " ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "folder = \"My Nice Folder\"\n", "filename = \"myfile.txt\"" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "# хочу сконструировать путь к файлу с именем, лежащем в filename,\n", "# внутри каталога, с именем, лежащим в folder" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File in folder «My Nice Folder».\n", "\n" ] } ], "source": [ "with open(os.path.join(folder, filename)) as f:\n", " print(f.read())" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'My Nice Folder/myfile.txt'" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.path.join(\"My Nice Folder\", \"myfile.txt\")" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'/Users/teacher'" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.getcwd()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Будьте внимательны! Мир кодировок полон неожиданных сюрпризов, поэтому, всегда когда неуверены, при открытии файла на чтение или на запись прямо указывайте параметр **encoding=**, чтобы обозначить ту кодировку, которую хотите использовать." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "with open(\"russiantext.txt\", \"w\", encoding=\"utf-8\") as f:\n", " print(\"Раз два три четыре пять,\", file=f)\n", " print(\"Вышел зайчик погулять!\", file=f)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Раз два три четыре пять,\n", "Вышел зайчик погулять!\n", "\n" ] } ], "source": [ "with open(\"russiantext.txt\", encoding='utf-8') as f:\n", " print(f.read())" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Раз РґРІР° три четыре пять,\n", "Вышел зайчик погулять!\n", "\n" ] } ], "source": [ "with open(\"russiantext.txt\", encoding='cp1251') as f:\n", " print(f.read())" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.2" } }, "nbformat": 4, "nbformat_minor": 2 }