设为首页 收藏本站
查看: 803|回复: 0

[经验分享] python的模块

[复制链接]

尚未签到

发表于 2018-8-5 10:42:15 | 显示全部楼层 |阅读模式
  参考:
  https://www.cnblogs.com/bobo0609/p/6938012.html
  https://docs.python.org/2/tutorial/modules.html
  1.简介
  在Python中,一个.py或者.pyc文件就称之为一个模块(Module)。即一个文件被看作一个独立的模块,一个模块也可以被看做是一个文件
  .py:存放的是python源码
  .pyc:存放的是python解释器对源码编译后的字节码
  python把文件名去掉.py/.pyc后缀作为模块名,比如 os.py ,那么它的模块名就是 os
  那么假设我们当前路径有个os.py,python怎么知道它的位置,并导入使用呢?
  这里就涉及到python的模块搜索路径,它的搜索次序如下:
  <1>当前路径
  <2>PYTHONPATH变量自定义的路径(PYTHONPATH是系统自定义的环境变量,类似centos中的PATH)
  <3>安装python时所定义的路径
  有人会疑惑,python怎么知道我当前的路径在哪?
  这是因为,python的程序包括一个顶层程序文件和其它的模块文件,这个顶层文件相当于程序执行的入口,类似shell脚本,我们执行脚本时必须写明绝对路劲或者切到对应路径去执行(这个时候路径就传递了),python也是同理
  例子:
        [root@cqhdtest python_learn]# pwd  /root/python_learn
  [root@cqhdtest python_learn]# cat getvalue.py
  #!/usr/local/anaconda2/bin/python
  x='Gx'
  y='Gy'
  z='Gz'
  def f1(x,y,z):
  x='Ex'
  z='Ez'
  print x,y,z
  def f2(x,y,z):
  x='Lx'
  print x,y,z
  f2(x,y,z)
  f1(x,y,z)
  [root@cqhdtest python_learn]# cat index.py
  import getvalue
  print x
  [root@cqhdtest python_learn]# python  index.py
  Ex Gy Ez
  Lx Gy Ez
  Traceback (most recent call last):
  File &quot;index.py&quot;, line 2, in <module>
  print x
  NameError: name 'x' is not defined
  这里index.py作为程序入口导入了getvalue这个模块,显然,这里python找到了getvalue模块,因为程序执行到了print x,但是为什么会有&quot;Ex Gy Ez&quot;这些输出呢?
  这是因为:python在首次导入模块(import 或者reload)的时候,会立即执行模块文件的顶层程序代码(不在函数内的代码,比如变量x'=Gx',函数定义def f1等,只要顶格写都会被执行),而位于函数主体内的代码直到函数被调用后才会执行,所以f1(x,y,z)函数被调用了,打印出了&quot;Ex Gy Ez&quot;,而f1又自己调用了f2,所以f2函数打印了&quot;Lx Gy Ez&quot;
  那么,既然模块有导入成功,x变量应该有定义,为何又提示“name 'x' is not defined”呢?
  这是因为:为了避免大家的相同编程习惯导致各种变量覆盖(比如张三和李四被分派写两个不同的模块,张三习惯在他的变量中使用x,李四也习惯这样,那么当两个模块都被导入时,因为变量名相同,必然有一个的值会被覆盖掉),于是python在导入模块时,以模块名新建一个新的名称空间,在新的名称空间中创建变量。 简单地说,当导入getvalue模块的x变量的时候,此时x不再被当成x,而是被当成getvalue.x
  例子:(接上例)
    [root@cqhdtest python_learn]# cat index.py  import getvalue
  print getvalue.x
  [root@cqhdtest python_learn]# python index.py
  Ex Gy Ez
  Lx Gy Ez
  Gx
  可以看见,此时的print 语句已经可以正常输出。
  那么,如果我想随时随地可以导入getvalue模块,而又不想切到指定路径去,那么该怎么办呢?
  这个时候,就要用到sys.path这个变量了
  例子:
        In [2]: import sys  

  In [3]: sys.path
  Out[3]:
  ['',
  '/usr/local/anaconda2/bin',
  '/usr/local/anaconda2/lib/python27.zip',
  '/usr/local/anaconda2/lib/python2.7',
  '/usr/local/anaconda2/lib/python2.7/plat-linux2',
  '/usr/local/anaconda2/lib/python2.7/lib-tk',
  '/usr/local/anaconda2/lib/python2.7/lib-old',
  '/usr/local/anaconda2/lib/python2.7/lib-dynload',
  '/usr/local/anaconda2/lib/python2.7/site-packages',
  '/usr/local/anaconda2/lib/python2.7/site-packages/IPython/extensions',
  '/root/.ipython']
  

  In [4]: sys.path.insert('/root/python_learn/')
  ---------------------------------------------------------------------------
  TypeError                                 Traceback (most recent call last)
  <ipython-input-4-b628fd39dcd4> in <module>()
  ----> 1 sys.path.insert('/root/python_learn/')
  

  TypeError: insert() takes exactly 2 arguments (1 given)
  

  In [5]: help (list.insert)
  

  

  In [6]: sys.path.insert(,'/root/python_learn/')
  File &quot;<ipython-input-6-c98c91c9451b>&quot;, line 1
  sys.path.insert(,'/root/python_learn/')
  ^
  SyntaxError: invalid syntax
  

  

  In [7]: sys.path.insert(0,'/root/python_learn/')
  

  In [8]: sys.path
  Out[8]:
  ['/root/python_learn/',
  '',
  '/usr/local/anaconda2/bin',
  '/usr/local/anaconda2/lib/python27.zip',
  '/usr/local/anaconda2/lib/python2.7',
  '/usr/local/anaconda2/lib/python2.7/plat-linux2',
  '/usr/local/anaconda2/lib/python2.7/lib-tk',
  '/usr/local/anaconda2/lib/python2.7/lib-old',
  '/usr/local/anaconda2/lib/python2.7/lib-dynload',
  '/usr/local/anaconda2/lib/python2.7/site-packages',
  '/usr/local/anaconda2/lib/python2.7/site-packages/IPython/extensions',
  '/root/.ipython']
  

  In [9]: import  getvalue
  Ex Gy Ez
  Lx Gy Ez
  

  In [10]: getvalue.x
  Out[10]: 'Gx'
  python按照sys.path的顺序来查找模块,需要注意的是,insert方法需要两个参数,第一个是索引,这里使用0,放在第一位,优先查找我们自己的目录
  如果我们再次import,python并不会再次执行顶层程序代码,而是简单地重载下内存中的对象
  例子:
        In [29]: import getvalue  

  In [30]: getvalue reload
  File &quot;<ipython-input-30-7cba10969034>&quot;, line 1
  getvalue reload
  ^
  SyntaxError: invalid syntax
  

  

  In [31]: help(reload)
  

  

  In [32]: reload(getvalue)
  Ex Gy Ez
  Lx Gy Ez
  Out[32]: <module 'getvalue' from '/root/python_learn/getvalue.pyc'>
  现在,模块加载没什么问题了,但是我觉得每次都要敲完整模块名getvalue,太烦人了,有没有什么办法呢?
  这个时候就要用到import-as语句了
  例子:
        In [33]: import getvalue as g  

  In [34]: g.x
  Out[34]: 'Gx'
  import xx  as x:把本来先创建名称空间名为getvlaue改成了g,所以调用就简单了,因为是修改所以此时getvalue这个名称空间是不存在的,所以不能用getvalue+'.'获取值
  那么如果我比较任性,就想覆盖当前环境中的变量x呢?
  这个时候就得用到from-import 语句了
  例子:
        In [35]: from getvalue import x  

  In [36]: x
  Out[36]: 'Gx'
  from-import语句只会加载对应的属性或者方法到当前的名称空间,所以其他语句不会执行
  所以python导入模块,大概分成以下几类:
  import:直接导入
  import Module as Module_alias:给变量取别名
  from Module import Attribute/Method: 导入部分属性/方法
  reload(Module):重新导入
  既然作为模块,就该有作为模块的觉悟,一导入就瞎执行是会被clear的-_-!!
  所以我们不该让模块中包含不该执行的语句,比如函数不该被调用。但是我又想这个模块文件有时作为程序顶层文件执行,有时作为模块被导入,那么有办法吗?
  这个时候就可以用到内置属性__name__了
  例子:
        [root@cqhdtest python_learn]# cp getvalue.py  New.py  [root@cqhdtest python_learn]# vi New.py
  [root@cqhdtest python_learn]# cat New.py
  #!/usr/local/anaconda2/bin/python
  x='Gx'
  y='Gy'
  z='Gz'
  def f1(x,y,z):
  x='Ex'
  z='Ez'
  print x,y,z
  def f2(x,y,z):
  x='Lx'
  print x,y,z
  f2(x,y,z)
  if __name__ == &quot;__main__&quot; :
  f1(x,y,z)
  [root@cqhdtest python_learn]# python New.py
  Ex Gy Ez
  Lx Gy Ez
  ============================================
  In [6]: import New
  

  In [7]: New.x
  Out[7]: 'Gx'
  

  In [8]: reload(New)
  Out[8]: <module 'New' from 'New.pyc'>
  

  In [9]: New.__name__
  Out[9]: 'New'
  这里的内置变量__name__,如果程序是顶层文件则为&quot;__main__&quot;,否则为模块名
  2.import的工作机制(摘抄自:https://www.cnblogs.com/bobo0609/p/6938012.html)
  import语句导入指定的模块时会执行3个步骤
  1. 找到模块文件:在模块搜索路径下搜索模块文件
  程序的主目录
  PYTHONPATH目录
  标准链接库目录
  2.编译成字节码:文件导入时会编译,因此,顶层文件的.pyc字节码文件在内部使用后会被丢弃,只有被导入的文件才会留下.pyc文件
  3.执行模块的代码来创建其所定义的对象:模块文件中的所有语句从头至尾依次执行,而此步骤中任何对变量名的赋值运算,都会产生所得到的模块文件的属性
  注意:模块只在第一次导入时才会执行如上步骤,后续的导入操作只不过是提取内存中已加载的模块对象,reload()可用于重新加载模块
  包: 用于将一组模块归并到一个目录中,此目录即为包,目录名即为包名
  包是一个有层次的文件目录结构,它定义了一个由模块和子包组成的Python应用执行环境
  基于包,Python在执行模块导入时可以指定模块的导入路径 import pack1.pack2.mod1
  每个包内都必须有__init__.py文件, __init__.py 可包含python代码,但通常为空,仅用于扮演包初始化、替目录产生模块命名空间以及使用目录导入时实现from*行为的角色

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-546902-1-1.html 上篇帖子: Python三级菜单实现 下篇帖子: python36安装
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表