任何Python程序都可以作为模块导入;在导入自己的模块时,需要添加路径:
import sys
sys.path.append('absolute-path');
(__pycache__是执行main.py时创建的)
hello.py内容:
def sayHello(): print('hello,world') |
main.py内容
import sys
sys.path.append("/home/icode0410/Documents/code/python/module/modules")
import hello hello.sayHello() |
运行main.py
$python3 main.py
hello,world
注意到,目录__pycache__被生成,里面一个hello.cpython-34.pyc文件(compiled python file);hello.cpython-34.pyc文件是执行import hello是生成的,该文件与平台无关;如果稍后又导入hello,Python会导入.pyc文件而不是.py文件。
删除.pyc文件并不会损害进程,只要.py文件存在即可,必要的时候会生成新的.pyc。
需要注意的是:模块第一次被导入时,其中的代码将被执行,其后再次导入便不会再被执行;
Python3以前,reload函数可以用于重新加载模块,而每次调用,模块的代码将被执行;Pyhon3中移除。
一般来讲,一个模块可能只需要定义一些函数或类,而不需要执行函数调用或者其他,但又需要一些测试代码存放其中,便于模块测试。
可以这样书写:
def sayHello():
print('hello,world')
if __name__ == '__main__' :
sayHello()
在模块导入的时候,__name__为模块名称;而在使用Python命令与执行脚本文件时,__name__为__main__;这样就满足了我们的需求。
模块位置
非默认路径中的module,需要使用sys.path.append添加进搜索路径;
使用下面的代码可以检测所有的搜索路径:
>>> import sys, pprint
>>> pprint.pprint(sys.path)
['',
'/usr/lib/python3.4',
'/usr/lib/python3.4/plat-x86_64-linux-gnu',
'/usr/lib/python3.4/lib-dynload',
'/usr/local/lib/python3.4/dist-packages',
'/usr/lib/python3/dist-packages']
参考help(pprint),pprint - Support to pretty-print lists, tuples, & dictionaries recursively.
package
为了组织好模块,可以将它们分组为包;包可以包含其他包,即嵌套。包就是一个目录,但需要包含一个__init__.py文件(模块)。如果将包作为普通文件导入的话,__init__.py文件的内容就是包的内容。
__init__文件内容:
packageinfo = {
'name' : 'hello',
'version' : '0.0.1'
}
hello.py内容:
def sayHello():
print("hello,world")
>>> import sys
>>> sys.path.append('/home/icode0410/Documents/code/python/module/packages')
>>> import hello
>>> hello.packageinfo
{'name': 'hello', 'version': '0.0.1'}
>>> hello.sayHello()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'sayHello'
>>> from hello import hello as h
>>> h.sayHello()
hello,world
__init__.py的文件被作为hello的内容,而hello.py则没有,需要另外导入;
dir
dir内建函数可以用于列出某个模块的所有内容:
>>> dir(h)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'sayHello']
__all__
可以在__init__.py文件中定义__all__变量,如:
__all__ = ['hello']
它告诉解释器,在执行from hello import *的时候,导入的模块包括'hello'。
>>> from hello import *
>>> hello.sayHello()
hello,world
>>> private
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'private' is not defined
private并没有被load,手动load:
>>> from hello import private
>>> private.private_hello
<function private_hello at 0x7f60f1dda840>
如果没有设定__all__,import*默认将会导入所有名称不以_开头的模块。