模块2



1. 两个模块相互引用

1.1 循环应用

a.py

from b import p_b                    # 用from module import func方式

def p_a():
    print "this is func in a"

if __name__ == "__main__":
    p_b()

b.py

from a import p_a                    # 用from module import func方式
def p_b():
    print "this is func in b"

if __name__ == "__main__":
    p_a()

进入python解释器

>>> import a                         # import a会报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "a.py", line 1, in <module>
    from b import p_b
  File "b.py", line 1, in <module>
    from a import p_a
ImportError: cannot import name p_a

python对module的导入过程是: sys.modules中找寻module入口,有则返回入口,无则创建入口。

上面第一次导入a,首先在sys.modules创建a入口,”from b import p_b”过程是:在sys.modules中创建一个b入口,然后执行b模块去找p_b

b模块中的第一句”from a import p_a”过程是:由sys.modules返回a入口,然后执行a模块去找p_a,于是又执行到了”from b import p_b”

至此形成了一个死循环

解决办法 a.py

import b

def p_a():
    print "this is func in a"

if __name__ == "__main__":
    p_b()

b.py

import a
def p_b():
    print "this is func in b"

if __name__ == "__main__":
    p_a()

进入python解释器

>>> import a
>>> import b
>>> a.p_a()
this is func in a
>>> b.p_b()
this is func in b

此时不会再报错,是因为我们只是需要模块入口,并没有继续要求import的过程里就完成模块的初始化,这样就打破了import时产生的死循环

扩展阅读

2. 关于import和from import,模块可以引入几次?

  1. from module import func会更加准确的引入一个func
  2. module is import just once(you can use reload() function but not recommend)

3. pyc vs pyo

3.1 什么是pyc

As an important speed-up of the start-up time for short programs that use a lot of standard modules, if a file called spam.pyc exists in the directory where spam.py is found, this is assumed to contain an already-“byte-compiled” version of the module spam. 当你执行程序需要import很多标准modules的时候,pyc就是一个很好的提速方法。

3.2 什么时候生成pyc

py程序被编译的时候,比如说import module时会生成

ls
a.py  b.py
# 进python解释器
>>> import a
>>> exit()
ls
a.py  a.pyc  b.py  b.pyc
# 之所以会出现b.pyc是因为我们在a里面import了b

主动生成方式

rm -f *.pyc
ls
a.py  b.py

python -m py_compile a.py

ls
a.py  a.pyc  b.py
# 这里没有产生b.pyc,因为我们只是手动编译了a.py,module a并没有初始化,所以就没产生b.pyc

3.3 pyc的作用是什么

3.4 什么是pyo (optimization)

The optimizer currently doesn’t help much; it only removes assert statements. 优化只是移除了assert 语句,并不能帮助太多

扩展(消除pyo):https://www.python.org/dev/peps/pep-0488/

3.5 什么时候生成pyo

用python -O 以优化模式进入解释器

python -O
>>> import a
>>> exit()
ls
a.py  a.pyc  a.pyo  b.py  b.pyo

# 手动创建
# rm -f *.py?
# ls
a.py  b.py
# python -O -m py_compile a.py
# ls
a.py  a.pyo  b.py

3.6 pyc和pyo的一些tips

3.7 模块总结

4. 包(Package)

4.1 什么是包?

Packages are a way of structuring Python’s module namespace by using “dotted module names”

包就是一种管理python module的方式,其命名空间使用”.modulenames”的方式

通俗理解:就是文件夹,不过文件夹下需要有一个init.py的文件

# 直接import的方式导入package
ls sixth_02
a.py  b.py  __init__.py 

>>> import sixth_02
>>> sixth_02.a.p_a()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'a'

# 包也是一个object,导入它并不能直接使用它下面的module,如果希望用直接导入package的方式,那需要在__init__.py下编辑。
cat sixth_02/__init__.py
from a import p_a

# 进入python解释器
>>> import sixth_02
>>> sixth_02.a.p_a()
this is func in a
>>> a.p_a()              #虽然我们在包里初始化import a,但是也不可以直接使用
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

# from package.package import module
>>> from sixth_02 import a
>>> a.p_a()
this is func in a

# from package.module import function
>>> from sixth_02.a import p_a
>>> p_a()
this is func in a

# import package.module
>>> import sixth_02.a
>>> sixth_02.a.p_a()
this is func in a

扩展:

文件夹的命名必须按照python中变量的命名方式

ls 6
a.py  b.py  __init__.py
>>> import 6
  File "<stdin>", line 1
    import 6
           ^
SyntaxError: invalid syntax

5. 补充相对路径和绝对路径

ls ./a.py
./a.py

# 进入python解释器
from .a import say_hi
from .. import b

6. 看看内置的Python模块有哪些

常用的:

扩展链接: https://docs.python.org/2.7/library/index.html

7. 要自律

熟悉flake8的使用,并据此改善之前的代码 https://pypi.python.org/pypi/flake8

8. 学习psutil的使用

安装方法:pip install psutil

作业,自学psutils的使用,完成下面题目

  1. 使用psutils收集系统信息:cpu核数,内存大小,系统启动时间,当前用户,然后写入文件:sys_info.log中
  2. 定时(每隔十分钟)收集系统信息:cpu使用率,内存使用率,网卡流量(in和out),包含时间一并写入到文件:monitor_sys_info.log

示例:

2015/08/14 08:10:00  cpu使用率    内存使用率   网络in流量    网卡out流量
2015/08/14 08:20:00  cpu使用率    内存使用率   网络in流量    网卡out流量

提示:

open(file_name, 'a')
f.write(line)
f.close()

通过a模式打开文件,可以向文件中追加数据。

#!/usr/bin/python

'''collect the sys info like cpu memory and network flow'''

import psutil


def get_sys_info():
    result = {
        'cpu_usage': psutil.cpu_percent(),
        'mem_usage': psutil.virtual_memory().percent,
        'net_in': psutil.net_io_counters().bytes_recv,
        'net_out': psutil.net_io_counters().bytes_sent
    }

    return result

 



if __name__ == '__main__':
    data = get_sys_info()
    with open('monitor_sys_info.log', 'a') as f:
        result = ["%s:%s" % (k, v) for k, v in data.items()]
        f.write('\t'.join(result)+"\n")

扩展

  • os.getlogin, 获取当前用户
  • psutil.user() , 获取用户列表
  • pip freeze, 查看安装的第三方模块(pip list)

SOURCE DISTRIBUTION: 查看文件组成结构可参考

  • sdist命令
  • manifest.in文件

还有其他这些文件

  • author
  • contribution-guide
  • requirements.txt
  • dev-requirements.txt