Last active
April 26, 2017 12:01
-
-
Save lysukhin/d33571730e8315b0edcd623e600151d0 to your computer and use it in GitHub Desktop.
Задание из анкеты для Я.Стажировки
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"*Пожалуйста, выполните небольшое задание. Напишите функцию — аналог команды du. Функция должна иметь один параметр — путь к каталогу — и возвращать сумму размеров всех файлов в этом каталоге, включая файлы во вложенных каталогах. Представьте, что вы запустили полученную функцию и команду du в одном и том же каталоге. Функция возвратила большее число, чем команда du. Почему так могло получиться? Как это исправить?*" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Начнем с того, что \"размер файла\" и \"место, занимаемое файлом на диске\" - это в общем случае не одно и то же. \n", | |
"\"Размером файла\" обычно называют собственно количество байт в файле. Пусть у нас есть файл `F.txt` размером FS = 15 КБ. \n", | |
"\n", | |
"Диск обычно разделен на блоки некоторого фиксированного размера; один и тот же блок не может быть \"поделен\" между двумя \"хозяевами\"-файлами. Пусть размер блока на нашем диске 4КБ.\n", | |
"Наш файл F, очевидно, потребует минимум 4 блока на диске (т.к. `3 x 4 = 12 < 15`), т.е. при собственном размере в 15 КБ он займет не менее 16 КБ. Обозначим размер занятого места за DS.\n", | |
"\n", | |
"Теперь непосредственно к команде `du`. Вызов **`du F.txt`** без дополнительных ключей вернёт число `(DS / 1024)`, т.е. (округлённый) размер занятого места на диске в КБ. Собственный размер файла (в байтах) можно узнать с ключом `--apparent-size:` **`du --apparent-size F.txt`**. В результате должны получить число `FS`. \n", | |
"\n", | |
"Тонким моментом является работа с разреженными (`sparse`) файлами, у которых собственный (`apparent`) размер может быть больше, чем размер на диске. Это происходит от того, что разреженные файлы содержат участки с последоватальностями нулей, которые файловая система не записывает на диск, но сохраняет информацию о том, где они расположены в файле.\n", | |
"\n", | |
"Т.к. нам нужна функция-аналог `du` без дополнительных параметров, напишем функцию, рекурсивно проходящуюся по всем вложенным директориям и возвращающую суммарный размер занятого места на диске вложенными файлами. Пустая директория тоже занимает место на диске (размер 1 блока). Библиотека `os` позволяет узнать как собственный размер файла, так и занимаемый размер на диске." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 249, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import os" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Напишем 2 функции: \n", | |
"+ `getFileSize()` для определения размера файла\n", | |
"+ `getDirSize()` для определения размера директории" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 260, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"def getFileSize(filename):\n", | |
" \n", | |
" stats = os.stat(filename)\n", | |
" \n", | |
" # получение собственного размера файла\n", | |
" fs = stats.st_size\n", | |
" \n", | |
" # получение занятого места на диске: (число блоков по 512 байт) х 512 \n", | |
" fs_d = stats.st_blocks * 512\n", | |
" \n", | |
" # возвращаем размеры в байтах\n", | |
" return (fs, fs_d) \n", | |
"\n", | |
"def getDirSize(path, ondisk=True):\n", | |
" \n", | |
" size = 0\n", | |
" ondisk = int(ondisk)\n", | |
" \n", | |
" # размер пустой директории\n", | |
" dirsize = 4096\n", | |
" \n", | |
" # цикл по всем поддиректориям\n", | |
" for root, subdirs, files in os.walk(path):\n", | |
" size_cur = dirsize + sum([getFileSize(root + '/' + f)[ondisk] for f in files])\n", | |
" size += size_cur\n", | |
" \n", | |
" # возвращаем размер в килобайтах (как и `du`)\n", | |
" return size / 1024" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Проверим работу `getFileSize()` на тестовом документе:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 261, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"(30, 4096)" | |
] | |
}, | |
"execution_count": 261, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"getFileSize(\"/data/test_dir/test_txt\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 262, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"30\t/data/test_dir/test_txt\n", | |
"4096\t/data/test_dir/test_txt\n" | |
] | |
} | |
], | |
"source": [ | |
"!du --apparent-size -B1 /data/test_dir/test_txt\n", | |
"!du -B1 /data/test_dir/test_txt" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Проверим работу `getDirSize()` на тестовой директории:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 271, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"32\n" | |
] | |
} | |
], | |
"source": [ | |
"print getDirSize(\"/data/test_dir/\", ondisk=True)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 272, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"8\t/data/test_dir/test_subdir_1/test_subdir_3\r\n", | |
"16\t/data/test_dir/test_subdir_1\r\n", | |
"4\t/data/test_dir/test_subdir_2/.hidden_test_subdir\r\n", | |
"8\t/data/test_dir/test_subdir_2\r\n", | |
"32\t/data/test_dir/\r\n" | |
] | |
} | |
], | |
"source": [ | |
"!du /data/test_dir/" | |
] | |
} | |
], | |
"metadata": { | |
"anaconda-cloud": {}, | |
"kernelspec": { | |
"display_name": "Python [conda root]", | |
"language": "python", | |
"name": "conda-root-py" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.12" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment