{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook demonstrates the `__path__` attribute. The `__path__` attribute is required to import \n",
"modules within packages. Having a `__path__` in a running notebook will permit relative imports.\n",
"\n",
"The post builds off [The Simplest importer for a notebook](http://nbviewer.jupyter.org/github/deathbeds/deathbeds.github.io/blob/master/deathbeds/2018-07-08-The-simplest-path-hook-importer-for-a-notebook.ipynb)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"('deathbeds.2018-07-08-The-simplest-path-hook-importer-for-a-notebook', ) {'origin': 'c:\\\\users\\\\deathbeds\\\\deathbeds.github.io\\\\deathbeds\\\\2018-07-08-The-simplest-path-hook-importer-for-a-notebook.ipynb', 'loader_state': None, 'is_package': False}\n"
]
}
],
"source": [
" from deathbeds import __The_simplest_path_hook_importer_for_a_notebook as importer\n",
" import sys, importlib, pytest\n",
" try: del __path__\n",
" except: ..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Typically my notebook is filled with garbage. The snippet below resets the normal `sys.path_hooks` behavior."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
" sys.path_hooks[1] = importlib._bootstrap_external.FileFinder.path_hook(importlib._bootstrap_external._get_supported_file_loaders())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add the simplest notebook importer as a `sys.path_hook`."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
" importer.new_loader((importer.NotebookLoader, ('.ipynb',)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Clear the importer cache (_forgetting this statement always slips me up_) and show the existing importers."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"((deathbeds.2018-07-08-The-simplest-path-hook-importer-for-a-notebook.NotebookLoader,\n",
" ('.ipynb',)),\n",
" (_frozen_importlib_external.ExtensionFileLoader,\n",
" ['.cp36-win_amd64.pyd', '.pyd']),\n",
" (_frozen_importlib_external.SourceFileLoader, ['.py', '.pyw']),\n",
" (_frozen_importlib_external.SourcelessFileLoader, ['.pyc']))"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
" sys.path_importer_cache.clear() or sys.path_hooks[1].__closure__[1].cell_contents"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Force remove the `__path__` from the namespace. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
" if __name__ == '__main__': globals().pop('__path__', None)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Demonstrate that `2018-11-26-Relative-imports` cannot be imported from `__main__`."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
" if __name__ == '__main__': \n",
" with pytest.raises(ImportError): importlib.import_module('.2018-11-26-Relative-imports', '__main__')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add the `__path__` back to the namespace."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
" __path__ = ['.']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Demonstrate that the module maybe imported."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
" module = importlib.import_module('.2018-11-26-Relative-imports', '__main__')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`Test` that `module` is a package relative to `__main__` and notebook."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Trying:\n",
" assert module.__package__ == '__main__'\n",
"Expecting nothing\n",
"ok\n",
"Trying:\n",
" assert module.__file__.endswith('.ipynb')\n",
"Expecting nothing\n",
"ok\n",
"1 items had no tests:\n",
" __main__\n",
"1 items passed all tests:\n",
" 2 tests in __main__.Test\n",
"2 tests in 2 items.\n",
"2 passed and 0 failed.\n",
"Test passed.\n"
]
}
],
"source": [
" class Test:\n",
" \"\"\">>> assert module.__package__ == '__main__'\n",
" >>> assert module.__file__.endswith('.ipynb')\"\"\"\n",
" if __name__ == '__main__': __import__('doctest').testmod(verbose=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.6.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}