CrazyWing:Python自动化运维开发实战 十五、Python模块

简介:

导语:

模块让你能够有逻辑地组织Python代码段。把相关的代码分配到一个模块里能让你的代码更好用,更易懂。模块也是Python对象,具有随机的名字属性用来绑定或引用。简单地说,模块就是一个保存了Python代码的文件。模块能定义函数,类和变量。模块里也能包含可执行的代码。

相关站点:

https://pypi.python.org/pypi/
PyPI(Python Package Index,PyPI) python包索引
为Internet上的第三方Python模块提供一个集中的存储库

制作模块

模块结构和布局:
用模块来合理组织你的 Python 代码是简单又自然的方法。你应该建立一种统一且容易阅读的结构,并将它应用到每一个文件中去。
下面就是一种非常合理的布局,一个典型模块的内部结构:

    # (1) 起始行(Unix) 
    # (2) 模块文档
    # (3) 模块导入
    # (4) 变量定义
    # (5) 类定义
    # (6) 函数定义
    # (7) 主程序

例:
一个叫做aname的模块里的Python代码一般都能在一个叫aname.py的文件中找到。

下例是个简单的模块mod.py:

[root@wing python]# cat mod.py
#!/usr/bin/env python
# coding=utf8
'''
这是一个模块实例
'''
import sys,os
name="wing"

def hello():
    print "hello world"

if __name__ =="__main__":
    hello()

使用模块:
In [1]: import mod

In [2]: mod.hello()
hello world

In [4]: print mod.__doc__
这是一个模块实例

In [5]: print mod.name
wing

import():

查询模块是内建模块还是属于某一个模块文件

In [5]: __import__("sys")
Out[5]: <module 'sys' (built-in)>

In [3]: __import__("os")
Out[3]: <module 'os' from '/usr/lib64/python2.7/os.pyc'>

In [4]: __import__("os").__file__
Out[4]: '/usr/lib64/python2.7/os.pyc'

内建变量name

可以使用两种方法调用main函数,但是每次在python解释器里第一次import模块pysysinfo_func时都会执行main函数如果又想可以把模块当脚本一样在命令行整体执行,又想在其他脚本调用模块内单独的某一个函数,可以使用第二种方式

#vim pysysinfo_func.py
#!/usr/bin/env python
import subprocess
def uname_func():
    uname = "uname"
    uname_arg = "-a"
    print "Gathering system information with %s command:\n" % uname
    subprocess.call([uname,uname_arg])

def disk_func():
    diskspace = "df"
    diskspace_arg = "-Th"
    print "Gathering diskspace information with %s command:\n" % diskspace
    subprocess.call([diskspace,diskspace_arg])

def main():
    uname_func()
    disk_func()

#第一种方式:
main()

#第二种方式:
if __name__ == "__main__":
    main()   

第一种方式的结果如下:会在导入模块的时候执行main函数
In [1]: import pysysinfo_func
Gathering system information with uname command:

Linux vm2.up.com 2.6.32-358.el6.x86_64 #1 SMP Tue Jan 29 11:47:41 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
Gathering diskspace information with df command:

Filesystem    Type    Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup-lv_root
              ext4     18G  4.1G   13G  25% /
tmpfs        tmpfs    565M  224K  565M   1% /dev/shm
/dev/sda1     ext4    485M   34M  427M   8% /boot
/dev/sr0   iso9660    3.5G  3.5G     0 100% /mnt

第二种方式的结果如下:
In [1]: import pysysinfo_func    //不会在导入模块的时候执行main函数

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

python中__name__的使用
1. 如果模块是被导入,__name__的值为模块名字
2. 如果模块是被直接执行,__name__的值为’__main__’

Py1.py
#!/usr/bin/env python
def test():
        print    '__name__ = ',__name__

if __name__ == '__main__':
        test()

Py2.py
#!/usr/bin/env python
import Py1.py
def test():
         print  '__name__ = ',__name__

if __name__ == '__main__':
         test()
         print ‘Py1.py __name__ = ’,Py1.__name__

执行结果:
        __name__=__main__
        Py1.py __name__=Py1

通过结果可以知道,Py2.py直接执行,那么内建变量__name__的值为__main__,否则为
模块的名字,通过这个特性可以
在if语句里面添加测试代码,可以提高减少BUG,提高程序的健壮性。
if __name__ == '__main__':
       test()

查看模块:

查看模块存放位置

通过查看模块存放路径就知道我们自己制作的模块应该放在哪个位置

查看python默认的模块存放路径。

>>> import sys
>>> sys.path
['', '/usr/local/python27/lib/python27.zip', '/usr/local/python27/lib/python2.7', '/usr/local/python27/lib/python2.7/plat-linux2', '/usr/local/python27/lib/python2.7/lib-tk', '/usr/local/python27/lib/python2.7/lib-old', '/usr/local/python27/lib/python2.7/lib-dynload', '/usr/local/python27/lib/python2.7/site-packages']
>>> 

列表内的第一个元素''表示当前工作目录,也就是说模块在当前目录下也可使用默认存放模块的目录是:/usr/local/python27/lib/python2.7/

查看模块内定义的各种标识符号

dir()函数
dir()函数返回一个排好序的字符串列表,内容是一个模块里定义过的名字。
返回的列表容纳了在一个模块里定义的所有模块,变量和函数。

实例:

#!/usr/bin/python
import math
content = dir(math)
print content;

输出结果:
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 
'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 
'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 
'sqrt', 'tan', 'tanh']

在这里,特殊字符串变量name指向模块的名字,file指向该模块的导入文件名。

调用模块

import 语句

想使用Python模块,只需在另一个源文件里执行import语句
语法如下:
import module1[, module2[,... moduleN] 
当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。

搜索路径:
是一个解释器会先进行搜索的所有目录的列表。如想要导入模块support.py,需要把命令放在脚本的顶端

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    # 导入模块
    import support 
    # 现在可以调用模块里包含的函数了
    support.print_func("Zara") 

以上实例输出结果:
    Hello : Zara 
一个模块只会被导入一次,不管你执行了多少次import。这样可以防止导入模块被一遍又一遍地执行。

From…import 语句

Python的from语句让你从模块中导入一个指定的部分到当前命名空间中。语法如下:
from modname import name1[, name2[, ... nameN]]
例如,要导入模块fib的fibonacci函数,使用如下语句:
from fib import fibonacci
这个声明不会把整个fib模块导入到当前的命名空间中,它只会将fib里的fibonacci单个引入到执行这个声明的模块的全局符号表。

From…import * 语句

把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明: 
from modname import *
这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。

定位模块

当你导入一个模块,Python解析器对模块位置的搜索顺序是:

• 当前目录
• 如果不在当前目录,Python 则搜索在 shell 变量 PYTHONPATH 下的每个目录。
• 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/。

模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。

PYTHONPATH变量
作为环境变量,PYTHONPATH由装在一个列表里的许多目录组成。PYTHONPATH的语法和shell
变量PATH的一样。
在Windows系统,典型的PYTHONPATH如下:
set PYTHONPATH=c:\python20\lib

在UNIX系统,典型的PYTHONPATH如下:
set PYTHONPATH=/usr/local/lib/python

python解释器开启时调用模块

正常情况下使用python解释器,使用模块的方法时需要导入模块,一些自己比较常用的模块比如os、process每次开始python解释器都得重新调用,下面的方法可以为你解除痛苦。

非常简单,只需设置一个变量,变量的值为某个.py文件的路径,在.py文件内设置预先想要导入的模块

# export PYTHONSTARTUP=/a.py

# cat /a.py 
import os
import subprocess

[root@vm2 ~]# python
>>> os.system("ls")       //可以看到测试的OS模块的时候可以直接使用,无需事先导入
模块OS
anaconda-ks.cfg  Documents    install.log.syslog  Public
a.py         Downloads    Music       Templates
我们可以利用上面得方法把tab键功能写入模块内事先导入

重载模块

reload()函数
当一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次。因此,如果你想重新执行模块里顶层部分的代码,可以用reload()函数。该函数会重新导入之前导入过的模块。
语法如下:
reload(module_name)
在这里,module_name要直接放模块的名字,而不是一个字符串形式。

比如想重载hello模块,如下:
reload(hello)

1.同一个模块导入,第一次代码全部运行,第二次很多的代码都不运行的,其实中间只是重复执行

2.尝试在第一次导入后,修改源文件,然后第二次导入,结果跟第一次一样。

原因:

导入操作的开销非常大,它把文件先编译成字节码,然后再导pvm(python virtual machine)上去执行,在编译的过程中,消耗资源非常多,所以,导入操作只编译执行一次,第二次只是重复执行,不再编译。
如果想再次执行完整的代码,就需要reload()这个函数,他会把源代码重新载入,然后执行一遍,但是在执行reload前,必须保证已经import那个模块。
注意:在python3里,执行reload前,请先执行from imp import reload,因为reload在python3里已经不再是内置函数。

例:

1.编写模块a.py
#!/usr/bin/env python
print "hello world"

2.进入Ipython倒入模块
In [1]: import a
hello world    第一次导入结果有输出

In [2]: import a
                    第二次导入结果就没有输出了
In [3]: import a
                    修改源文件后再次导入仍然没有输出结果
In [4]: 
必须的用reload()重载模块才行

发布自己的模块

以之前处理嵌套列表的代码为例,把他做成可以发给别人使用的模块

1.创建父目录:
#mkdir /nester

2.准备源代码文件:
#vim /nester/nester.py
#!/usr/bin/env python
#coding=utf-8
"这是模块文档字符串"
def print_list(name):
"这是函数文档字符串"
for each_item in name:
if isinstance(each_item,list):
print_list(each_item)
else:
print each_item

3.准备setup.py文件:

vim /nester/setup.py

    #!/usr/bin/env python
    from distutils.core import setup
    setup(
        name = 'nester',
        version = '1.0.0',
        py_modules = ['nester'],
        author = 'wing',
        author_email = '276267003@qq.com',
        url = 'www.fklinux.com',
        description = 'A simple printer of nested lists',
    )

4.构建发布文件:

cd /nester

    # python setup.py sdist

5.构建成功之后/nester目录下会出现dist目录,dist目录下会出现构建好的模块打包文件,这个文件就可以发给别人使用了
[root@host nester]# ls dist/
nester-1.0.0.tar.gz

6.测试安装模块:
#tar xvzf nester-1.0.0.tar.gz
#cd nester-1.0.0
#python setup.py install
#python

>> import nester //其实到这里,如果你能导入模块成功的话,恭喜你,^_^说明你的模块儿没问题了,下面是这个模块的具体使用
>> a=[1,2,3,[4,5,[6,7]]]
>> nester.print_list(a)
1
2
3
4
5
6
7

Python中的包

包是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的Python的应用环境。

例子:

1.创建目录Phone,作为包名
#mkdir /Phone   

2.分别创建模块文件pots.py、lsdn.py和G3.py
#cat /Phone/pots.py
#!/usr/bin/python
def Pots():
   print "I'm Pots Phone"

#cat /Phone/Isdn.py
#!/usr/bin/python
def Lsdn():
   print "I'm lsdn Phone"

#cat /Phone/G3.py  
#!/usr/bin/python
def G3():
   print "I'm G3 Phone"

3.在/Phone目录下创建文件 __init__.py:
#cat /Phone/__init__.py
from Pots import Pots
from Isdn import Isdn
from G3 import G3 

4.使用包:
#!/usr/bin/python
# 导入 Phone 包
import Phone

Phone.Pots()
Phone.Isdn()
Phone.G3() 

输出结果:
I'm Pots Phone
I'm 3G Phone
I'm ISDN Phone 
如上,为了举例,只在每个文件里放置了一个函数,但其实你可以放置许多函数。你也可以在这些文件里定义Python的类,然后为这些类建一个包。

制作tab补全模块:

如果在python编辑器里tab键不能补全,可以自己定义一个tab.py程序,然后当作模块导入就可以使用tab键补全了

#cat tab.py
#!/usr/bin/env python
import sys,readline,rlcompleter,os  
readline.parse_and_bind('tab: complete')
histfile = os.path.join(os.environ['HOME'],'.pythonhistory')

把自己编写的tab模块拷贝到默认模块目录下,如果不拷贝到默认位置也可以使用,不过需要在进入python shell的当前目录下存放tab.py
#mv tab.py /usr/local/python27/lib/python2.7/

tab模块使用:

>> import tab

上面的方式在使用tab模块的时候跟使用其他模块一样每次都需要手动导入,如果你像我一样比较懒^_^,可以使用下面的方法,在启动python shell的时候就自动导入我们想让他导入的模块

python shell自动导入模块:

1.创建一个脚本文件:

cat /root/.startup.py

    #!/usr/bin/evn python
    import tab
    print "module loaded"

2.设置PYTHONSTARTUP环境变量:
#export PYTHONSTARTUP=/root/.startup.py //如何永久生效?你懂的

3.测试:

python

    Python 2.7.10 (default, Dec 13 2016, 10:54:54) 
    [GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    module loaded
本文转自 CrazyWing 51CTO博客,原文链接:http://blog.51cto.com/fklinux/2050113
相关文章
|
13天前
|
存储 缓存 JavaScript
python实战篇:利用request库打造自己的翻译接口
python实战篇:利用request库打造自己的翻译接口
26 1
python实战篇:利用request库打造自己的翻译接口
|
29天前
|
数据采集 JSON API
如何实现高效率超简洁的实时数据采集?——Python实战电商数据采集API接口
你是否曾为获取重要数据而感到困扰?是否因为数据封锁而无法获取所需信息?是否因为数据格式混乱而头疼?现在,所有这些问题都可以迎刃而解。让我为大家介绍一款强大的数据采集API接口。
|
30天前
|
数据采集 Python
爬虫实战-Python爬取百度当天热搜内容
爬虫实战-Python爬取百度当天热搜内容
65 0
|
1月前
|
安全 C++ Python
小游戏实战-Python实现石头剪刀布+扫雷小游戏
小游戏实战-Python实现石头剪刀布+扫雷小游戏
33 0
|
1月前
|
安全 Java 关系型数据库
深入探究Python的多线程与异步编程:实战与最佳实践
【2月更文挑战第1天】 深入探究Python的多线程与异步编程:实战与最佳实践
110 0
|
1月前
|
数据可视化 API Python
画图实战-Python实现某产品全年销量数据多种样式可视化
画图实战-Python实现某产品全年销量数据多种样式可视化
38 0
|
1月前
|
自然语言处理 小程序 数据挖掘
数据分析实战-Python实现博客评论数据的情感分析
数据分析实战-Python实现博客评论数据的情感分析
95 0
|
29天前
|
人工智能 运维 监控
构建高性能微服务架构:现代后端开发的挑战与策略构建高效自动化运维系统的关键策略
【2月更文挑战第30天】 随着企业应用的复杂性增加,传统的单体应用架构已经难以满足快速迭代和高可用性的需求。微服务架构作为解决方案,以其服务的细粒度、独立性和弹性而受到青睐。本文将深入探讨如何构建一个高性能的微服务系统,包括关键的设计原则、常用的技术栈选择以及性能优化的最佳实践。我们将分析微服务在处理分布式事务、数据一致性以及服务发现等方面的挑战,并提出相应的解决策略。通过实例分析和案例研究,我们的目标是为后端开发人员提供一套实用的指南,帮助他们构建出既能快速响应市场变化,又能保持高效率和稳定性的微服务系统。 【2月更文挑战第30天】随着信息技术的飞速发展,企业对于信息系统的稳定性和效率要求
|
4天前
|
API 调度 开发者
深入理解Python异步编程:从Asyncio到实战应用
在现代软件开发中,异步编程技术已成为提升应用性能和响应速度的关键策略。本文将通过实例讲解Python中的异步编程核心库Asyncio的基本概念、关键功能以及其在Web开发中的应用。我们不仅将理论与实践结合,还将展示如何通过实际代码示例解决常见的并发问题,帮助开发者更有效地利用Python进行异步编程。
|
6天前
|
SQL API 数据库
Python中的SQLAlchemy框架:深度解析与实战应用
【4月更文挑战第13天】在Python的众多ORM(对象关系映射)框架中,SQLAlchemy以其功能强大、灵活性和易扩展性脱颖而出,成为许多开发者首选的数据库操作工具。本文将深入探讨SQLAlchemy的核心概念、功能特点以及实战应用,帮助读者更好地理解和使用这一框架。

热门文章

最新文章