Python Playbook - Ch10 Modules and Packages
===
###### tags: `python` `presentation`
## 10.1. Making a Hierarchical Package of Modules
> Organize your code on the file system and make sure that every directory defines an ```__init__.py``` file.
```shell
graphics/
__init__.py
primitive/
__init__.py
line.py
fill.py
text.py
formats/
__init__.py
png.py
jpg.py
```
```python=
import graphics.primitive.line
from graphics.primitive import line
import graphics.formats.jpg as jpg
```
## 10.2. Controlling the Import of Everything
Define a variable ```__all__``` in your module that explicitly lists the exported names.
```python
from somemodule import *
# somemodule.py
def spam():
pass
def grok():
pass
blah = 42
# Only export 'spam' and 'grok'
__all__ = ['spam', 'grok']
```
## 10.3. Importing Package Submodules Using Relative Names
1. Import a module located in the same directory:
```python
# in line.py (see 10.1)
from . import fill
```
2. Import a module located in a different directory:
```python
# in line.py (see 10.1)
from ..formats import png
```
## 10.4. Splitting a Module into Multiple Files
A program module can be split into separate files by turning it into a package.
```python
from mymodule.a import A
from mymodule.b import B
# or
from mymodule import A, B
```
## 10.5. Making Separate Directories of Code Import Under a Common Namespace
To unify separate directories under a common namespace
1. omit \_\_init\_\_.py files in the directories where the components are going to join together.
```shell
foo-package/
spam/
blah.py
bar-package/
spam/
grok.py
```
2. Add into Python Module path
```python
import sys
sys.path.extend(['foo-package', 'bar-package'])
import spam.blah
import spam.grok
```
3. use ```__path__``` to check namespaces
```python
>>>import spam
>>> spam.__path__
>>>_NamespacePath(['foo-package/spam', 'bar-package/spam'])
```
4. Namespace module should not have attribute ```__file__```
## 10.6. Reloading Modules
To reload a previously loaded module, use [module].reload().
:::warning
:warning: reload() does not update definitions that have been imported using statements such as ```from module import name```.
:::
## 10.7. Making a Directory or Zip File Runnable As a Main Script
If ``__main__.py`` is present, you can simply run the Python interpreter on the top-level directory like this:
```bash
% python3 myapplication
```
The interpreter will execute the ```__main__.py``` file as the main program.
## 10.8. Reading Datafiles Within a Package
The ```pkgutil.get_data()``` function is meant to be a high-level tool for getting a datafile
regardless of where or how a package has been installed.
```python
import pkgutil
data = pkgutil.get_data(__package__, 'somedata.dat')
```
> The built-in I/O functions such as open() have to be programmed to use **absolute** filenames.
## 10.9. Adding Directories to sys.path
:question: You have Python code that can’t be imported because it’s not located in a directory listed in sys.path. You can
1. Add them through the use of the **PYTHONPATH** environment variable
```bash
% env PYTHONPATH=/some/dir:/other/dir python3
```
2. Create a .pth file that lists the directories, and place it into one of Python’s ++site-packages++ directories.
```bash
# myapplication.pth
/some/dir
/other/dir
```
> Reference: [撥開 Python, pip, site-packages 的藍色蜘蛛網](https://medium.com/@will.wang/%E6%92%A5%E9%96%8B-python-pip-site-packages-%E7%9A%84%E8%97%8D%E8%89%B2%E8%9C%98%E8%9B%9B%E7%B6%B2-90e398bb3785)
> Reference: [Python 的 Import 陷阱](https://medium.com/pyladies-taiwan/python-%E7%9A%84-import-%E9%99%B7%E9%98%B1-3538e74f57e3)
## 10.10. Importing Modules Using a Name Given in a String
Use the ```importlib.import_module()``` function to manually import a module or part of a package where the name is given as a string.
## 10.11. Loading Modules from a Remote Machine Using Import Hooks
This particular solution involves installing an instance of a special finder object UrlMetaFinder as the last entry in sys.meta_path. Whenever modules are imported, thefinders in ```sys.meta_path``` are consulted in order to locate the module.
[```importlib.abc```](https://docs.python.org/3/library/importlib.html) – Abstract base classes related to import

## 10.12. Patching Modules on Import
Use the same import hook machinery as 10.11.

```python
sys.meta_path.insert(0, PostImportFinder())
```
## 10.13. Installing Packages Just for Yourself
To force packages to install in this directory, give the --user option to the installation command. For example:
```shell
python3 setup.py install --user
```
or
```shell
pip install --user packagename
```
## 10.14. Creating a New Python Environment
You can make a new “virtual” environment using the ```pyvenv``` command.
```bash=
% pyvenv Spam
% ls
bin include lib pyvenv.cfg
```
## 10.15. Distributing Packages
If you’re going to start giving code away, make sure the
1. ```setup.py```
2. ```MANIFEST.in```
files appear in the top-level directory of yourpackage.
**[Reference]** [Python application 的打包和发布——(上)](http://wsfdl.com/python/2015/09/06/Python%E5%BA%94%E7%94%A8%E7%9A%84%E6%89%93%E5%8C%85%E5%92%8C%E5%8F%91%E5%B8%83%E4%B8%8A.html)