mushroom的博客

作为一枚经常被嘲笑是菜鸟的测试,在追猪的路上越走越远……喂,那头自称是爆裂码手的猪,你等等我(°°)~...

Python模块(跨目录)调用总结

系统模块调用

    说到模块调用,大家应该都对import有个基本的了解,在项目里面非常常见的比如import time,from selenium import webdriver等,我们经常在python中通过from...import.../import...的语法可以引用一些系统模块,把系统模块引入后就可以调用模块里面定义好的方法,例如:

from time import ctime

print ctime()

import time

print time.ctime()

上面两个写法的最终目的都是为了获取并打印当前时间,

方法一中通过引入time模块,导入其下面的ctime方法,实现对ctime()方法的调用,因为用了from,指定了所需调用下面具体的ctime方法,在用的时候直接写方法名ctime()就可以调用了,

方法二里面是直接引入了整个time模块,在用的时候需要加入模块名再进行其下面方法的引用time.ctime()。

自定义模块调用

    我们在进行编码设计的时候,往往需要自定义一些模块,其他程序可以调用这些模块,那么方法和原理还是和上面的系统模块调用是差不多的,让我们来举个栗子:

先创建一个目录ModPython,下面定义一个公共模块PublicA.py ,为了更好的理解,我都是写的简单的方法的栗子。

#PublicA.py
def PubA():
	print "I'm PublicA in /ModPythonh/PublicA.py"

接下来,还是在这个目录下新建一个python程序A.py去调用这个自定义的模块

#A.py
import PublicA
PublicA.PubA()

运行A.py的结果如下:

I am def PubA_1 in /ModPythonh/PublicA.py
[Finished in 1.1s]

结果成功地打印了PublicA.py里面的PubA()方法,说明这次调用成功了~

让我们来看看刚刚这个目录结构,因为PublicA和A这两个脚本都是在ModPython里面的,所以直接用import引用进来就好了:

ModPython/

-------------/ PublicA.py

-------------/A.py

这个时候如果我们在ModPython这个项目里新建一个文件夹B,里面新建一个b1.py和b2.py两个文件,目录和具体内容如下:

ModPython/

-------------/ PublicA.py

-------------/A.py

-------------/B

-------------/B                  /b1.py

-------------/B                  /b2.py

#b1.py
def b1_1():
	print "I am def b1_1 in /ModPythonh/B/b1.py"

def b1_2():
	print "I am def b1_2 in /ModPythonh/B/b1.py"
#b2.py
def b2_1():
	print "I am def b2_1 in /ModPythonh/B/b2.py"

def b2_2():
	print "I am def b2_2 in /ModPythonh/B/b2.py"

这个时候我们在A.py中import b1,然后b1.b1_1(),试试能不能成功……

这个时候报错了:ImportError: No module named b1,提示说没有b1这个模块,为什么呢,因为b1和执行程序A.py不在一个目录下,所以查找不到,这个时候该怎么解决,下面,咳咳(敲黑板(o゚v゚)ノ)重点请看……

Python跨目录的模块调用

继续用上面已经建好的目录,然后继续按下面的规则来点更复杂的,建好了我们再依次来说说不同情况的跨目录模块调用……ModPython/

-------------/A.py
-------------/PublicA.py
-------------/B /b1.py
-------------/B /b2.py
-------------/C /c.py

在ModPython里面再建文件夹C,里面新建一个c.py文件,文件建好了,那我们就来具体分情况说说吧。

同级目录下子文件调用

在我们文件结构中,与A.py同级的有PublicA.py还有就是B、C目录了,那么对于A.py来说,b1、b2、c就是子文件了。

如果我们想要在A.py里面调用b1,需要怎么做呢?

如果直接进行import b1,上面试过了会报错,找不到模块b1,因为b1和A不再一个目录下。

那么我们就找到b1的父级目录B,B和和A.py在一个目录下,将B作为一个模块,b1、b2都作为模块里面的方法去调用,为了让系统知道B是一个模块,我们需要在B下面新建一个叫做__init__.py的文件,内容可以为空,这个文件可以告诉python B是一个可以调用的模块了。

-------------/B /__init__.py

建好后我们再到A.py中来调用 执行一下:

from B import b1,b2
b1.b1_1()
b2.b2_2()

运行结果:

I am def b1_1 in /ModPythonh/B/b1.py

I am def b2_2 in /ModPythonh/B/b2.py

这样就没有问题啦,我们再来补充一下另外两种写法也是可以的:

#A.py
from B.b1 import *
b1_1()
#A.py
import B.b1
B.b1.b1_1()

上面的三种方法都是基于__init__.py文件是空的时候,我个人比较喜欢第一种,但是问题来了,如果B下面有很多的文件,我每次调用可能需要的是不同的方法,能不能在每次调用的时候直接写:

from B import *

b1.b1_1()
b2.b2_2()

我们可以试着执行一下,看看行不行,这个时候提示:NameError: name 'b1' is not defined,如果想要在每次执行调用的时候直接引入B下面的所有模块,我们就需要在__init__.py文件中加入引入:

#__init__.py
import b1,b2

这样就能够直接写import * 啦。

同级目录之间的跨模块调用

ModPython
---------/A.py
---------/PublicA.py
---------/B /__init__.py
---------/B /b1.py
---------/B /b2.py

---------/C /c.py

我们再来看这个目录结构,梳理一下,对于B、C来说他们是同级的,b1和c也是同级的,如果我们需要在c里面调用b该怎么做呢?如果像之前A.py调用的那样,还是会出现这个眼熟的error:ImportError: No module named B,导入的是B模块,而B和c.py文件也不是在一个目录下的了,如果需要那样调用,那么就要先回到上级目录C,再开始from B import b1

跳转目录这个操作,我们需要调用python的sys模块进行实现,具体实现方法如下:

#c.py
import sys
sys.path.append('..')
from B import b1

b1.b1_1()

用append()方法进行追加,..表示回到上一级目录中去。

再来看我们这个栗子,c.py回到上一级就是C这个目录了,对于C来说,和B就是同级目录,B下面已经创建了__init__.py文件,已经是个模块可以用来引入,这个时候from B  import b1就没有问题可以顺利调用啦。

了解到这里,关于python跨目录调用自定义模块的问题基本就得以解决了,实在不行,还有一个万能的方法(偷笑(/▽\)):

只要在被调用文件所属的文件夹下创建好__init__.py文件,然后引入sys模块,在用append进行追加的时候直接写上需要调用文件的绝对路径。

比如上面,我们要调用B里面的文件,只需要找到B的绝对路径,假设是C:\Users\ModPython\B,那append就这么写:

sys.path.append('C:\\Users\\ModPython')

这样就不管什么情况,都可以找到啦~~~~


关于.pyc文件的一点理解

    在上述的各种自定义模块调用的操作后,如果回到之前新建的目录再多看一眼,相信不难发现,多出了几个.pyc文件,比如上面的b1.pyc、__init__.pyc,为什么会生成这些pyc文件,pyc文件又是有什么作用呢,我查阅了点资料在此说一下我的理解。

首先,来看一下python的运行和编译机制的几个步骤:

python运行自然要依赖解释器,解释器会将python源码转换为字节码,然后再执行转换好的字节码。

那么当我们在引入调用一些模块时……

  1. 模块加载的过程中,源码就被虚拟机(解释器)翻译成了PyCodeObject对象(也就是字节码)
  2. 将PyCodeObject写入了CPU,下次运行将直接从内存中进行读取指令并执行程序
  3. 执行结束后,根据执行的方式决定是否将执行的结果写回硬盘,也就是复制到.pyc文件中
  4. 当再次执行时,先检查是否有.pyc文件,有的话,再检查字节码文件与自身的修改时间是否一致,一致则直接运行.pyc文件,不一致或是没有字节码文件则从新执行前面三个 步骤。

所以,我们前面调用过的模块都有生成一个.pyc文件。

从上面的步骤进行分析,就可以看出.pyc文件相对与.py文件来说,由于是执行过并写入内存空间的,所以加载速度会比.py文件要快,可以加速程序的运行。

当然了,由于执行起来.pyc和.py是一样的,.py是直接以源码的形式进行呈现,而.pyc只是字节码文件,在某种程度上来说,还可以防止代码被偷看,具有一定的隐藏效果……

虽然对于菜鸡我而言,估计也没人偷看我代码ㄟ( ▔, ▔ )ㄏ


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32897143/article/details/79960432
个人分类: Python
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

Python模块(跨目录)调用总结

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭