diff --git a/06-Modules and Packages/.ipynb_checkpoints/Useful_Info_Notebook-checkpoint.ipynb b/06-Modules and Packages/.ipynb_checkpoints/Useful_Info_Notebook-checkpoint.ipynb new file mode 100644 index 000000000..f7317b76d --- /dev/null +++ b/06-Modules and Packages/.ipynb_checkpoints/Useful_Info_Notebook-checkpoint.ipynb @@ -0,0 +1,386 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Modules and Packages\n", + "\n", + "In this section we briefly:\n", + "* code out a basic module and show how to import it into a Python script\n", + "* run a Python script from a Jupyter cell\n", + "* show how command line arguments can be passed into a script\n", + "\n", + "Check out the video lectures for more info and resources for this.\n", + "\n", + "The best online resource is the official docs:\n", + "https://docs.python.org/3/tutorial/modules.html#packages\n", + "\n", + "But I really like the info here: https://python4astronomers.github.io/installation/packages.html\n", + "\n", + "## Writing modules" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing file1.py\n" + ] + } + ], + "source": [ + "%%writefile file1.py\n", + "def myfunc(x):\n", + " return [num for num in range(x) if num%2==0]\n", + "list1 = myfunc(11)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**file1.py** is going to be used as a module.\n", + "\n", + "Note that it doesn't print or return anything,\n", + "it just defines a function called *myfunc* and a variable called *list1*.\n", + "## Writing scripts" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing file2.py\n" + ] + } + ], + "source": [ + "%%writefile file2.py\n", + "import file1\n", + "file1.list1.append(12)\n", + "print(file1.list1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**file2.py** is a Python script.\n", + "\n", + "First, we import our **file1** module (note the lack of a .py extension)
\n", + "Next, we access the *list1* variable inside **file1**, and perform a list method on it.
\n", + "`.append(12)` proves we're working with a Python list object, and not just a string.
\n", + "Finally, we tell our script to print the modified list.\n", + "## Running scripts" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 2, 4, 6, 8, 10, 12]\n" + ] + } + ], + "source": [ + "! python file2.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we run our script from the command line. The exclamation point is a Jupyter trick that lets you run command line statements from inside a jupyter cell." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 2, 4, 6, 8, 10]\n" + ] + } + ], + "source": [ + "import file1\n", + "print(file1.list1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above cell proves that we never altered **file1.py**, we just appended a number to the list *after* it was brought into **file2**." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Passing command line arguments\n", + "Python's `sys` module gives you access to command line arguments when calling scripts." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing file3.py\n" + ] + } + ], + "source": [ + "%%writefile file3.py\n", + "import sys\n", + "import file1\n", + "num = int(sys.argv[1])\n", + "print(file1.myfunc(num))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that we selected the second item in the list of arguments with `sys.argv[1]`.
\n", + "This is because the list created with `sys.argv` always starts with the name of the file being used.
" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]\n" + ] + } + ], + "source": [ + "! python file3.py 21" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we're passing 21 to be the upper range value used by the *myfunc* function in **list1.py**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Understanding modules\n", + "\n", + "Modules in Python are simply Python files with the .py extension, which implement a set of functions. Modules are imported from other modules using the import command.\n", + "\n", + "To import a module, we use the import command. Check out the full list of built-in modules in the Python standard library [here](https://docs.python.org/3/py-modindex.html).\n", + "\n", + "The first time a module is loaded into a running Python script, it is initialized by executing the code in the module once. If another module in your code imports the same module again, it will not be loaded twice but once only - so local variables inside the module act as a \"singleton\" - they are initialized only once.\n", + "\n", + "If we want to import the math module, we simply import the name of the module:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# import the library\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# use it (ceiling rounding)\n", + "math.ceil(2.4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Exploring built-in modules\n", + "Two very important functions come in handy when exploring modules in Python - the dir and help functions.\n", + "\n", + "We can look for which functions are implemented in each module by using the dir function:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']\n" + ] + } + ], + "source": [ + "print(dir(math))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we find the function in the module we want to use, we can read about it more using the help function, inside the Python interpreter:\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on built-in function ceil in module math:\n", + "\n", + "ceil(...)\n", + " ceil(x)\n", + " \n", + " Return the ceiling of x as an Integral.\n", + " This is the smallest integer >= x.\n", + "\n" + ] + } + ], + "source": [ + "help(math.ceil)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Writing modules\n", + "Writing Python modules is very simple. To create a module of your own, simply create a new .py file with the module name, and then import it using the Python file name (without the .py extension) using the import command.\n", + "\n", + "## Writing packages\n", + "Packages are name-spaces which contain multiple packages and modules themselves. They are simply directories, but with a twist.\n", + "\n", + "Each package in Python is a directory which MUST contain a special file called **\\__init\\__.py**. This file can be empty, and it indicates that the directory it contains is a Python package, so it can be imported the same way a module can be imported.\n", + "\n", + "If we create a directory called foo, which marks the package name, we can then create a module inside that package called bar. We also must not forget to add the **\\__init\\__.py** file inside the foo directory.\n", + "\n", + "To use the module bar, we can import it in two ways:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# Just an example, this won't work\n", + "import foo.bar" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# OR could do it this way\n", + "from foo import bar" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the first method, we must use the foo prefix whenever we access the module bar. In the second method, we don't, because we import the module to our module's name-space.\n", + "\n", + "The **\\__init\\__.py** file can also decide which modules the package exports as the API, while keeping other modules internal, by overriding the **\\__all\\__** variable, like so:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "__init__.py:\n", + "\n", + "__all__ = [\"bar\"]" + ] + } + ], + "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.2" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/06-Modules and Packages/Useful_Info_Notebook.ipynb b/06-Modules and Packages/Useful_Info_Notebook.ipynb index 786b0485a..f7317b76d 100644 --- a/06-Modules and Packages/Useful_Info_Notebook.ipynb +++ b/06-Modules and Packages/Useful_Info_Notebook.ipynb @@ -6,20 +6,201 @@ "source": [ "# Modules and Packages\n", "\n", - "There's no code here because it didn't really make sense for the section. Check out the video lectures for more info and the resources for this.\n", + "In this section we briefly:\n", + "* code out a basic module and show how to import it into a Python script\n", + "* run a Python script from a Jupyter cell\n", + "* show how command line arguments can be passed into a script\n", "\n", - "Here is the best source the official docs!\n", + "Check out the video lectures for more info and resources for this.\n", + "\n", + "The best online resource is the official docs:\n", "https://docs.python.org/3/tutorial/modules.html#packages\n", "\n", "But I really like the info here: https://python4astronomers.github.io/installation/packages.html\n", "\n", - "Here's some extra info to help:" + "## Writing modules" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing file1.py\n" + ] + } + ], + "source": [ + "%%writefile file1.py\n", + "def myfunc(x):\n", + " return [num for num in range(x) if num%2==0]\n", + "list1 = myfunc(11)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**file1.py** is going to be used as a module.\n", + "\n", + "Note that it doesn't print or return anything,\n", + "it just defines a function called *myfunc* and a variable called *list1*.\n", + "## Writing scripts" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing file2.py\n" + ] + } + ], + "source": [ + "%%writefile file2.py\n", + "import file1\n", + "file1.list1.append(12)\n", + "print(file1.list1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**file2.py** is a Python script.\n", + "\n", + "First, we import our **file1** module (note the lack of a .py extension)
\n", + "Next, we access the *list1* variable inside **file1**, and perform a list method on it.
\n", + "`.append(12)` proves we're working with a Python list object, and not just a string.
\n", + "Finally, we tell our script to print the modified list.\n", + "## Running scripts" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 2, 4, 6, 8, 10, 12]\n" + ] + } + ], + "source": [ + "! python file2.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we run our script from the command line. The exclamation point is a Jupyter trick that lets you run command line statements from inside a jupyter cell." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 2, 4, 6, 8, 10]\n" + ] + } + ], + "source": [ + "import file1\n", + "print(file1.list1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above cell proves that we never altered **file1.py**, we just appended a number to the list *after* it was brought into **file2**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "## Passing command line arguments\n", + "Python's `sys` module gives you access to command line arguments when calling scripts." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Writing file3.py\n" + ] + } + ], + "source": [ + "%%writefile file3.py\n", + "import sys\n", + "import file1\n", + "num = int(sys.argv[1])\n", + "print(file1.myfunc(num))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that we selected the second item in the list of arguments with `sys.argv[1]`.
\n", + "This is because the list created with `sys.argv` always starts with the name of the file being used.
" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]\n" + ] + } + ], + "source": [ + "! python file3.py 21" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we're passing 21 to be the upper range value used by the *myfunc* function in **list1.py**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Understanding modules\n", + "\n", "Modules in Python are simply Python files with the .py extension, which implement a set of functions. Modules are imported from other modules using the import command.\n", "\n", "To import a module, we use the import command. Check out the full list of built-in modules in the Python standard library [here](https://docs.python.org/3/py-modindex.html).\n", @@ -31,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -41,7 +222,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -50,7 +231,7 @@ "3" ] }, - "execution_count": 2, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -72,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -97,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 10, "metadata": {}, "outputs": [ { diff --git a/06-Modules and Packages/__pycache__/file1.cpython-36.pyc b/06-Modules and Packages/__pycache__/file1.cpython-36.pyc new file mode 100644 index 000000000..33faa982b Binary files /dev/null and b/06-Modules and Packages/__pycache__/file1.cpython-36.pyc differ diff --git a/06-Modules and Packages/file1.py b/06-Modules and Packages/file1.py new file mode 100644 index 000000000..67b593624 --- /dev/null +++ b/06-Modules and Packages/file1.py @@ -0,0 +1,3 @@ +def myfunc(x): + return [num for num in range(x) if num%2==0] +list1 = myfunc(11) \ No newline at end of file diff --git a/06-Modules and Packages/file2.py b/06-Modules and Packages/file2.py new file mode 100644 index 000000000..4b63a64a4 --- /dev/null +++ b/06-Modules and Packages/file2.py @@ -0,0 +1,3 @@ +import file1 +file1.list1.append(12) +print(file1.list1) \ No newline at end of file diff --git a/06-Modules and Packages/file3.py b/06-Modules and Packages/file3.py new file mode 100644 index 000000000..dcc44eac5 --- /dev/null +++ b/06-Modules and Packages/file3.py @@ -0,0 +1,4 @@ +import sys +import file1 +num = int(sys.argv[1]) +print(file1.myfunc(num)) \ No newline at end of file