markdown Python模块(模块化)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown Python模块(模块化)相关的知识,希望对你有一定的参考价值。
参考资料: <<Python Cookbook第三版>> 第10章
代码库: 详见python-snippets仓库
## 关于module和package的理解
> .py是一个script, 当用-m 和包名的方式运行的时候, 是一个module, 若在某个文件夹层级有\_\_init\_\_.py文件, 那么这个文件夹就是一个package. 可以通过package name进行导入. 实际上一个package就是一个大的module, 一个package相当于将一个module拆分成了多个代码文件.
module是和命名空间\(namespace\)关联的, 一个module对应一个命名空间. 如果要查看命名空间, 直接`print(module_name)`或者`print(package_name)`.
```bash
graphics/
__init__.py
primitive/
__init__.py
line.py
formats/
__init__.py
png.py
jpg.py
```
以上述层级组织后, 就可以进行如下导入了
```python
import graphics.primitive.line
from graphics.primitive import line
import graphics.formats.jpg as jpg
```
导入的时候, 上级的init.py会顺次先于最终导入的文件进行初始化操作.
## 关于\_\_all\_\_变量
\_\_all\_\_变量是限制了`from <somemodule or package> import *`这种导入方式的导入成员, 实际上是为了最大限度减少命名空间的名称冲突, 但是`from somemodule import concrete_name`这种不会受到影响, 而且`import somemodule`这种的也不会受到影响.
[参考链接1](https://blog.csdn.net/orangleliu/article/details/49848413)
[参考链接2](https://blog.csdn.net/nivana999/article/details/39620673)
### 使用相对引入
注意只有from语句生效, 只有package组织形式的生效. 使用相对引入的好处是避免了在代码中对包名的硬编码.
当使用了相对引入的时候, 必须把.py当成模块执行才会生效, 当成脚本来执行会fail, 当成模块来执行就是加上\-m参数. 一个例子:
```python
% python3 mypackage/A/spam.py # Relative imports fail
% python3 -m mypackage.A.spam # Relative imports work
```
## 将module拆分成多个文件, 作为package存在
> 当一个module膨胀的时候, 需要拆分代码, 然后作为一个package的形式存在.
思考: 实际上package(文件夹)都是先以module(py文件)的形式存在, 当代码逐渐增多的时候, module就会升级为package, 实际上从用户层面来看, 是无法看出package和module的区别的.
例子:
拆分前源代码:
```python
# mymodule.py
class A:
def spam(self):
print('A.spam')
class B(A):
def bar(self):
print('B.bar')
```
拆分后代码:
```python
# 目录结构
mymodule/
__init__.py
a.py
b.py
# a.py
class A:
def spam(self):
print('A.spam')
# b.py
from .a import A
class B(A):
def bar(self):
print('B.bar')
# __init__.py
from .a import A
from .b import B
```
## namespace package
> 与普通的package不同的是, 在top level package不要加\_\_init\_\_.py文件即可. 通常在大框架或者需要多人开发plug\-in或者add\-on的时候需要这种package
```bash
# 层级结构, foo和bar是不同人维护的
foo-package/
spam/
blah.py
bar-package/
spam/
grok.py
```
使用:
```python
import sys
# 注意这样执行的时候要保证pwd为脚本所在路径, 才能使用相对路径
sys.path.extend(['foo-package', 'bar-package'])
import spam.grok
import spam.blah
import pyspark
# print(spam.__file__) # 输出:AttributeError: 'module' object has no attribute '__file__'
print(spam) # 输出:<module 'spam' (namespace)>
print(sys) # 输出:<module 'sys' (built-in)>
print(pyspark) # 输出:<module 'pyspark' from '/usr/local/lib/python3.6/site-packages/pyspark/__init__.py'>
```
## Python 打包为可执行文件
> 如果只是简单的想把几个脚本组合在一起交付给某人使用, 并不是为了作为一个standard library module来使用, 那么无需创建一个package, 直接放到文件夹打包并放置一个\-\_main\_\_.py文件即可.
```bash
# 层级结构
myapplication/
spam.py
bar.py
grok.py
__main__.py
# 运行
bash % python3 myapplication
# 打包运行
bash % ls spam.py bar.py grok.py
bash % zip -r myapp.zip *.py
bash % python3 myapp.zip
... output from __main__.py ...
```
以上是关于markdown Python模块(模块化)的主要内容,如果未能解决你的问题,请参考以下文章
markdown 与Python相关的模块和指南。
markdown Python模块安装
markdown ImportError:没有名为'_tkinter'的模块,请安装python3-tk包
markdown JavaScript的模块化编程
Python3基础 import...as 给导入的模块起别名
Python3基础 __file__ 查询模块的完整路径