{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Модули и пакеты #"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте поговорим об организации кода на Python.\n",
    "\n",
    "В реальных проектах, конечно, никто код в один файлик не пишет. Это очень быстро становится громоздким и неподдерживаемым. Представьте проекты, где тысячи или даже сотни тысяч строк кода. Конечно, код надо разделять по смыслу, по назначению. И в Python'е это разделение предоставляется механизмом модулей и пакетов.\n",
    "\n",
    "Что такое модуль в Python? Модуль в Python мы с вами уже создавали, когда экспериментировали с интерактивным интерпретатором. Модуль в Python - это, по сути, файлик с расширением.py, который содержит определения переменных, функций, классов, и который также может содержать импорты других модулей. Давайте мы с вами начнем знакомство с модулем и создадим наш новый модуль."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Перейдем в консоль, создадим директорию `playground`, в которой мы будем работать. Перейдем в нее.\n",
    "\n",
    "```shell\n",
    "mkdir playground\n",
    "cd playground\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте создадим модуль, назовем его `mymodule`.\n",
    "\n",
    "```shell\n",
    "vim mymodule.py\n",
    "```\n",
    "\n",
    "Опять же обратите внимание на расширение.py."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Внутри `mymodule` мы можем писать код. Как я говорил, модуль может содержать импорты. Давайте начнем знакомиться с импортами и посмотрим на импорт модуля из стандартной библиотеки. Это делается с помощью ключевого слова `import`. Мы сейчас заимпортируем модуль стандартной библиотеки `sys`.\n",
    "\n",
    "```python\n",
    "import sys\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Модуль `sys` содержит всевозможные переменные, структуры, функции для того, чтобы посмотреть на что-то, связанное с интерпретатором Python. В данном случае мы посмотрим на то, где Python ищет модули по умолчанию. Эта информация находится внутри переменной `sys.path`, давайте напечатаем ее на экран.\n",
    "\n",
    "```python\n",
    "print(sys.path)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Как мы с вами уже делали, мы можем запустить модуль напрямую с помощью `python3`. Мы видим на экране, что с режима переменной `sys.path` вывелось. Это список директорий, в которых Python по умолчанию ищет модули. Обратите внимание, что на первом месте написана директория, в которой мы сейчас находимся.\n",
    "\n",
    "```shell\n",
    "python3 mymodule.py\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['C:\\\\Users\\\\MikhaylovAF\\\\Python\\\\1. Введение в Python\\\\4. Организация кода и окружение', 'C:\\\\ProgramData\\\\Anaconda3\\\\python38.zip', 'C:\\\\ProgramData\\\\Anaconda3\\\\DLLs', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib', 'C:\\\\ProgramData\\\\Anaconda3', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\locket-0.2.1-py3.8.egg', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32\\\\lib', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\Pythonwin']\n"
     ]
    }
   ],
   "source": [
    "! python mymodule.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте убедимся в этом. Утилита `pwd` показывает нашу текущую директорию. То есть Python будет искать модули в этой директории в первую очередь, поэтому ничто нам не мешает запустить интерактивный интерпретатор Python и попробовать заимпортировать наш модуль. Сделаем это."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['C:\\\\Users\\\\MikhaylovAF\\\\Python\\\\1. Введение в Python\\\\4. Организация кода и окружение', 'C:\\\\ProgramData\\\\Anaconda3\\\\python38.zip', 'C:\\\\ProgramData\\\\Anaconda3\\\\DLLs', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib', 'C:\\\\ProgramData\\\\Anaconda3', '', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\locket-0.2.1-py3.8.egg', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\win32\\\\lib', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\Pythonwin', 'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\site-packages\\\\IPython\\\\extensions', 'C:\\\\Users\\\\MikhaylovAF\\\\.ipython']\n"
     ]
    }
   ],
   "source": [
    "import mymodule"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`import mymodule`, и видим, что у нас получилось. Что важно отметить, это то, что если мы попробуем сделать `import mymodule` еще раз, то ничего на экран не выведется. Это связано с тем, что Python импортирует модуль только один раз. Он импортирует имя модуля в локальное пространство имен, и в дальнейшем, если мы делаем точно такой же импорт, импорта не происходит, потому что Python видит, что мы уже ранее этот модуль импортировали, импорт закеширован."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Когда происходит импорт, что вообще происходит? Python импортирует модуль и выполняет все инструкции, которые в этом модуле на верхнем уровне определены. Собственно он наши инструкции, которые мы написали в файлике `mymodule.py` и выполнил.\n",
    "\n",
    "Давайте пойдем дальше. Иногда модулей недостаточно. Иногда код нужно объединять по смыслу в более крупные объединения, такие как пакеты."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Пакеты в Python, по сути, это директория, которая содержит один или больше модулей. Внутри пакетов могут содержаться другие пакеты. Давайте посмотрим на примере и создадим пакет. Пакет, по сути, является тем же самым модулем. Но давайте создадим пакет, назовем его `mypackage`. Это директория, и внутри директории `mypackage` давайте создадим пустой файлик `__init__.py`. Обратите внимание на название этого файла. Оно начинается с двух символов подчеркивания, заканчивается ими и с расширением `py`.\n",
    "\n",
    "```shell\n",
    "mkdir mypackage\n",
    "touch mypackage/__init__.py\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Это специальный файл, который должен содержать пакет для того, чтобы интерпретироваться Python'ом как пакет. На самом деле начиная с Python'a 3.3 есть так называемый `mainspace packages`, который не требует наличия `__init__.py` файлика в них. Но мы будем с вами рассматривать обычные `regular packages`, которые вы обычно будете видеть на практике."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Что это за файлик `__init__.py`? Это файл, который будет выполняться каждый раз, когда мы импортируем наш пакет. Давайте посмотрим на примере. Откроем наш модуль, который мы писали, `mymodule.py` и заменим импорты. Теперь мы будем импортировать не модуль стандартной библиотеки, а пакет, который мы только что создали. И давайте напечатаем, что это за объект такой `mypackage`, который мы заимпортировали.\n",
    "\n",
    "```python\n",
    "import mypackage\n",
    "\n",
    "print(mypackage)\n",
    "```\n",
    "\n",
    "Сохраняем и запускаем с помощью `python3`.\n",
    "\n",
    "```shell\n",
    "python3 mymodule.py\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<module 'mypackage' from 'C:\\\\Users\\\\MikhaylovAF\\\\Python\\\\1. Введение в Python\\\\4. Организация кода и окружение\\\\mypackage\\\\__init__.py'>\n"
     ]
    }
   ],
   "source": [
    "! python mymodule.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Мы видим, что у нас импорт прошел успешно, мы не получили никаких ошибок, и видим, что mypackage на самом деле представляет собой модуль. Как я и говорил, пакеты - это тоже модули. Давайте теперь внутри файлика `__init__.py` в модуле `mypackage` напишем немножко кода.\n",
    "\n",
    "```shell\n",
    "vim mypackage/__init__.py\n",
    "```\n",
    "\n",
    "Мы напишем здесь `print(\"importing mypackage\")`. Целью нашей является удостовериться, что файлик `__init__.py` вызывается каждый раз, когда мы импортируем пакет `mypackage` из нашего модуля `mymodule`. Вот мы видим, что на экран напечаталась строка, которую мы написали. Это значит, что файлик `__init__.py` был выполнен при импорте."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "importing mypackage\n",
      "<module 'mypackage' from 'C:\\\\Users\\\\MikhaylovAF\\\\Python\\\\1. Введение в Python\\\\4. Организация кода и окружение\\\\mypackage\\\\__init__.py'>\n"
     ]
    }
   ],
   "source": [
    "! python mymodule.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте посмотрим на директорию, которая у нас получилась. Мы видим, что мы создали `mymodule.py`, а также пакет, который содержит файлик `__init__.py`.\n",
    "\n",
    "```shell\n",
    "tree\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Однако обратите внимание, что помимо тех директорий и файлов, которые мы создавали сами, Python автоматически создал директорию, которая называется `__pycache__` с двумя подчеркиваниями в начале и в конце, а также файлик `_init_.pyc`. Что это такое? Директория `__pycache__` и файлик с расширением.pyc содержат скомпилированное представление нашего кода. \n",
    "\n",
    "Виртуальная машина Python не выполняет напрямую код, который мы пишем сами, она прежде всего его преобразовывает в оптимизированное внутреннее представление, которое называется байткодом. Соответственно, директории `__pycache__` и файлы с расширением.pyc содержат как раз такое соптимизированное представление нашего кода, то есть байткод. Про то, что такое байткод и зачем он нужен, мы с вами будем говорить в отдельной лекции, а сейчас просто не пугайтесь, когда вы увидите вот такие автоматически созданные Python'ом файлы."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте пойдем дальше и еще поговорим об импортах и организации кода на Python'е. Откроем наш модуль. Очень часто на практике вы будете видеть вот такую конструкцию.\n",
    "\n",
    "```python\n",
    "if __name__ == \"__main__\":\n",
    "    print(\"Hello\")\n",
    "```\n",
    "\n",
    "Что это значит? Каждый модуль содержит в своем пространстве имен переменную `__name__` с двумя подчеркиваниями, которая определяет название модуля, в котором выполняется код. Это позволяет разделить те моменты, когда наш модуль используется напрямую интерпретатором Python, либо он был импортирован из другого модуля. Что это значит - лучше посмотреть на примере.\n",
    "\n",
    "Давайте попробуем выполнить наш модуль напрямую интерпретатором Python. Модуль выполнился, и мы видим, что строка \"hello\" напечаталась на экран."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "importing mypackage\n",
      "Hello\n"
     ]
    }
   ],
   "source": [
    "! python mymodule.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Однако если мы сейчас зайдем в интерактивный интерпретатор и попробуем заимпортировать наш модуль, мы видим, что строка \"hello\" не напечаталась."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "importing mypackage\n"
     ]
    }
   ],
   "source": [
    "import mymodule"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Это как раз благодаря той проверке на то, как вызывается наш модуль, `if __name__ == \"_main__\"`. Мы можем таким образом контролировать, какие кусочки кода в каких условиях у нас вызываются. Далее.\n",
    "\n",
    "Следующее, что мы посмотрим, это как внутри пакета создавать свои отдельные модули, как я уже сказал, пакет является объединением одного и более модулей, и как оттуда импортировать код. Синтаксис импортов в Python достаточно богат, поэтому мы сейчас это осветим. Давайте создадим внутри директории `mypackage` новый модуль, который будет называться `utils.py`.\n",
    "\n",
    "```shell\n",
    "vim mypackage/utils.py\n",
    "```\n",
    "\n",
    "В этом модуле мы объявим функцию. С функциями вы пока не знакомы, и у нас в следующих блоках будут отдельная лекция, посвященная им. Однако давайте сейчас напишем самую простую функцию, которая будет называться `multiply`, и она будет перемножать два значения, которые ей передали в качестве аргументов, и возвращать результат этого умножения. Функция в Python записывается с помощью ключевого слова `def`, ну вы это еще увидите в дальнейшем.\n",
    "\n",
    "```python\n",
    "def multiply(a, b):\n",
    "    return a * b\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Пока наша задача - посмотреть, как эту функцию можно заимпортировать, находясь внутри `mymodule`, который мы с вами написали. Давайте посмотрим на структуру, которая у нас получилась. Вот файлик `utils.py`, который мы только что создали, он внутри пакета `mypackage`. Как нам получить функцию `multiply` внутри `mymodule`? На самом деле, все, что нам нужно сделать - это сделать вот такой импорт, `import mypackage.utils`. Теперь мы можем обращаться к функции `multiply` вот таким вот образом - `mypackage.utils.multiply`. Давайте умножим 2 и 3.\n",
    "\n",
    "```shell\n",
    "vim mymodule.py\n",
    "```\n",
    "\n",
    "Сохраним и вызовем `python3`. У нас получилось."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "importing mypackage\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "! python mymodule.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Мы видим, что в результате выполнения нашей программы, получилось число 6. Однако это достаточно длинная запись. В Python'е есть конструкция `from…import`. Что это значит? Что мы можем переписать наш импорт вот таким образом, используя `from mypackage.utils import`, и дальше название нашей функции, которую мы прописали в модуле `utils`. Тогда в коде мы можем обращаться к этой функции просто по ее имени, потому что она при импорте была добавлена в локальное пространство имен.\n",
    "\n",
    "```python\n",
    "from mypackage.utils import multiply\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    print(multiply(2, 3))\n",
    "```\n",
    "\n",
    "Опять же запустим - то же самое."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "importing mypackage\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "! python mymodule.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Есть еще возможность. Есть такой синтаксис, как `import` звездочка. То есть он записывается вот так, `import *`. Это позволяет из модуля `utils` заимпортировать все объявления, которые там содержатся.\n",
    "\n",
    "```python\n",
    "from mypackage.utils import *\n",
    "\n",
    "multiply(2, 3)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "importing mypackage\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "! python mymodule.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "В данном случае у нас там содержится только функция `multiply`. Она будет заимпортирована, и мы можем ее использовать. Запустим - то же самое. Однако такой импорт со звездочкой не рекомендуется к использованию на практике, потому что он неявный. И в большинстве случаев его используют при экспериментах в интерактивном интерпретаторе, возможно при тестировании кода, но не советуют использовать при написании кода приложений и при импортах из каких-то библиотек.\n",
    "\n",
    "Последнее, что нам осталось посмотреть в работе модулей — это то, как посмотреть, где, например, находится модуль, который мы заимпортировали. Давайте попробуем это сделать. Под словами \"где он находится\" я имею в виду, где на диске. В Python есть такой замечательный модуль, который называется `this`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The Zen of Python, by Tim Peters\n",
      "\n",
      "Beautiful is better than ugly.\n",
      "Explicit is better than implicit.\n",
      "Simple is better than complex.\n",
      "Complex is better than complicated.\n",
      "Flat is better than nested.\n",
      "Sparse is better than dense.\n",
      "Readability counts.\n",
      "Special cases aren't special enough to break the rules.\n",
      "Although practicality beats purity.\n",
      "Errors should never pass silently.\n",
      "Unless explicitly silenced.\n",
      "In the face of ambiguity, refuse the temptation to guess.\n",
      "There should be one-- and preferably only one --obvious way to do it.\n",
      "Although that way may not be obvious at first unless you're Dutch.\n",
      "Now is better than never.\n",
      "Although never is often better than *right* now.\n",
      "If the implementation is hard to explain, it's a bad idea.\n",
      "If the implementation is easy to explain, it may be a good idea.\n",
      "Namespaces are one honking great idea -- let's do more of those!\n"
     ]
    }
   ],
   "source": [
    "import this"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Давайте сделаем `import this`, и видим, что на экран вывелся набор утверждений, которым должен следовать каждый Python-программист. Давайте посмотрим на первые два. `Beautiful is better than ugly` - красивое лучше, чем некрасивое. Логично. Второе - `Explicit is better than implicit` — явное лучше неявного. Это очень важный принцип. Посмотрите на все эти утверждения. Они забавные, интересные и в целом справедливые. Однако напоминаю, что наша цель — посмотреть, откуда же он был заимпортирован. В Python существуют богатые средства интроспекции, которые предоставляет модуль стандартной библиотеки `inspect`. Мы его импортируем и дальше воспользуемся функцией `getfile` из этого модуля, чтобы посмотреть, где находится модуль `this`. Передаем название модуля `this` и видим путь на жестком диске, на котором хранится наш модуль `this.py`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\this.py'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import inspect\n",
    "\n",
    "inspect.getfile(this)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "На вашей операционной системе результат будет, скорее всего, другим. Нас в данном случае интересует директория. А какие же еще модули содержатся в этой директории, помимо `this`? Давайте посмотрим. Сделаем импорт из модуля `os` — это модуль стандартной библиотеки, который позволяет работать с операционной системой. И в модуле `os` есть функция `listdir`, которая позволяет получить содержимое той или иной директории. Мы передаем ей наш путь, который мы только что скопировали, и получаем список файлов, которые находятся в этой директории. Посмотрите на этот огромный список."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['abc.py',\n",
       " 'aifc.py',\n",
       " 'antigravity.py',\n",
       " 'argparse.py',\n",
       " 'ast.py',\n",
       " 'asynchat.py',\n",
       " 'asyncio',\n",
       " 'asyncore.py',\n",
       " 'base64.py',\n",
       " 'bdb.py',\n",
       " 'binhex.py',\n",
       " 'bisect.py',\n",
       " 'bz2.py',\n",
       " 'calendar.py',\n",
       " 'cgi.py',\n",
       " 'cgitb.py',\n",
       " 'chunk.py',\n",
       " 'cmd.py',\n",
       " 'code.py',\n",
       " 'codecs.py',\n",
       " 'codeop.py',\n",
       " 'collections',\n",
       " 'colorsys.py',\n",
       " 'compileall.py',\n",
       " 'concurrent',\n",
       " 'configparser.py',\n",
       " 'contextlib.py',\n",
       " 'contextvars.py',\n",
       " 'copy.py',\n",
       " 'copyreg.py',\n",
       " 'cProfile.py',\n",
       " 'crypt.py',\n",
       " 'csv.py',\n",
       " 'ctypes',\n",
       " 'curses',\n",
       " 'dataclasses.py',\n",
       " 'datetime.py',\n",
       " 'dbm',\n",
       " 'decimal.py',\n",
       " 'difflib.py',\n",
       " 'dis.py',\n",
       " 'distutils',\n",
       " 'doctest.py',\n",
       " 'dummy_threading.py',\n",
       " 'email',\n",
       " 'encodings',\n",
       " 'ensurepip',\n",
       " 'enum.py',\n",
       " 'filecmp.py',\n",
       " 'fileinput.py',\n",
       " 'fnmatch.py',\n",
       " 'formatter.py',\n",
       " 'fractions.py',\n",
       " 'ftplib.py',\n",
       " 'functools.py',\n",
       " 'genericpath.py',\n",
       " 'getopt.py',\n",
       " 'getpass.py',\n",
       " 'gettext.py',\n",
       " 'glob.py',\n",
       " 'gzip.py',\n",
       " 'hashlib.py',\n",
       " 'heapq.py',\n",
       " 'hmac.py',\n",
       " 'html',\n",
       " 'http',\n",
       " 'idlelib',\n",
       " 'imaplib.py',\n",
       " 'imghdr.py',\n",
       " 'imp.py',\n",
       " 'importlib',\n",
       " 'inspect.py',\n",
       " 'io.py',\n",
       " 'ipaddress.py',\n",
       " 'json',\n",
       " 'keyword.py',\n",
       " 'lib2to3',\n",
       " 'libLIEF.dll',\n",
       " 'libLIEF.lib',\n",
       " 'linecache.py',\n",
       " 'locale.py',\n",
       " 'logging',\n",
       " 'lzma.py',\n",
       " 'mailbox.py',\n",
       " 'mailcap.py',\n",
       " 'mimetypes.py',\n",
       " 'modulefinder.py',\n",
       " 'msilib',\n",
       " 'multiprocessing',\n",
       " 'netrc.py',\n",
       " 'nntplib.py',\n",
       " 'ntpath.py',\n",
       " 'nturl2path.py',\n",
       " 'numbers.py',\n",
       " 'opcode.py',\n",
       " 'operator.py',\n",
       " 'optparse.py',\n",
       " 'os.py',\n",
       " 'pathlib.py',\n",
       " 'pdb.py',\n",
       " 'pickle.py',\n",
       " 'pickletools.py',\n",
       " 'pipes.py',\n",
       " 'pkgutil.py',\n",
       " 'platform.py',\n",
       " 'plistlib.py',\n",
       " 'poplib.py',\n",
       " 'posixpath.py',\n",
       " 'pprint.py',\n",
       " 'profile.py',\n",
       " 'pstats.py',\n",
       " 'pty.py',\n",
       " 'pyclbr.py',\n",
       " 'pydoc.py',\n",
       " 'pydoc_data',\n",
       " 'py_compile.py',\n",
       " 'queue.py',\n",
       " 'quopri.py',\n",
       " 'random.py',\n",
       " 're.py',\n",
       " 'reprlib.py',\n",
       " 'rlcompleter.py',\n",
       " 'runpy.py',\n",
       " 'sched.py',\n",
       " 'secrets.py',\n",
       " 'selectors.py',\n",
       " 'shelve.py',\n",
       " 'shlex.py',\n",
       " 'shutil.py',\n",
       " 'signal.py',\n",
       " 'site-packages',\n",
       " 'site.py',\n",
       " 'smtpd.py',\n",
       " 'smtplib.py',\n",
       " 'sndhdr.py',\n",
       " 'socket.py',\n",
       " 'socketserver.py',\n",
       " 'sqlite3',\n",
       " 'sre_compile.py',\n",
       " 'sre_constants.py',\n",
       " 'sre_parse.py',\n",
       " 'ssl.py',\n",
       " 'stat.py',\n",
       " 'statistics.py',\n",
       " 'string.py',\n",
       " 'stringprep.py',\n",
       " 'struct.py',\n",
       " 'subprocess.py',\n",
       " 'sunau.py',\n",
       " 'symbol.py',\n",
       " 'symtable.py',\n",
       " 'sysconfig.py',\n",
       " 'tabnanny.py',\n",
       " 'tarfile.py',\n",
       " 'telnetlib.py',\n",
       " 'tempfile.py',\n",
       " 'test',\n",
       " 'textwrap.py',\n",
       " 'this.py',\n",
       " 'threading.py',\n",
       " 'timeit.py',\n",
       " 'tkinter',\n",
       " 'token.py',\n",
       " 'tokenize.py',\n",
       " 'trace.py',\n",
       " 'traceback.py',\n",
       " 'tracemalloc.py',\n",
       " 'tty.py',\n",
       " 'turtle.py',\n",
       " 'turtledemo',\n",
       " 'types.py',\n",
       " 'typing.py',\n",
       " 'unittest',\n",
       " 'urllib',\n",
       " 'uu.py',\n",
       " 'uuid.py',\n",
       " 'venv',\n",
       " 'warnings.py',\n",
       " 'wave.py',\n",
       " 'weakref.py',\n",
       " 'webbrowser.py',\n",
       " 'wsgiref',\n",
       " 'xdrlib.py',\n",
       " 'xml',\n",
       " 'xmlrpc',\n",
       " 'zipapp.py',\n",
       " 'zipfile.py',\n",
       " 'zipimport.py',\n",
       " '_bootlocale.py',\n",
       " '_collections_abc.py',\n",
       " '_compat_pickle.py',\n",
       " '_compression.py',\n",
       " '_dummy_thread.py',\n",
       " '_markupbase.py',\n",
       " '_nsis.py',\n",
       " '_osx_support.py',\n",
       " '_pydecimal.py',\n",
       " '_pyio.py',\n",
       " '_py_abc.py',\n",
       " '_sitebuiltins.py',\n",
       " '_strptime.py',\n",
       " '_system_path.py',\n",
       " '_threading_local.py',\n",
       " '_weakrefset.py',\n",
       " '__future__.py',\n",
       " '__phello__.foo.py',\n",
       " '__pycache__']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "os.listdir(\"C:\\\\ProgramData\\\\Anaconda3\\\\lib\\\\\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Это все модули стандартной библиотеки в Python, коих просто тонны. Там есть модули на все случаи жизни. И с какой-то частью из этих модулей мы вас познакомим в рамках нашего курса в дальнейшем. Однако может так получиться, что даже этой богатой функциональности, которая есть в стандартной библиотеке Python, вам может не хватить — у вас какая-то специфичная задача. Не отчаивайтесь, Python — это язык с огромным сообществом, и существует масса библиотек, написанных этим сообществом на все случаи жизни, которые вы можете установить в свою систему. Эти библиотеки находятся на ресурсе `pypi.org`, и вы в любой момент можете зайти на этот ресурс, посмотреть, какая библиотека вам нужна, и установить ее в вашу систему. А установка пакета стороннего в систему производиться с помощью утилиты `pip`, и мы с вами на следующей лекции посмотрим, как стороннюю библиотеку в вашу систему можно поставить.\n",
    "\n",
    "На этой лекции мы познакомились с организацией кода на Python, посмотрели, что такое модули и что такое пакеты, и как их организовывать, как импортировать код из модулей и пакетов. Также с некоторыми особенностями, которые с модулями и пакетами связаны. Нас ждет в дальнейшем еще немало работы с модулями стандартной библиотеки. Теперь вы умеете ими пользоваться."
   ]
  }
 ],
 "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.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
