[python]from import详解以及不同目录之间模块的调用

5,239 阅读7分钟

参考网址

wenku.baidu.com/view/2571f8…

前言

import语句用来导入其他python文件(称为模块module),
使用该模块里定义的类、方法或者变量,从而达到代码复用的目的。
文中给大家提到import 语句的两种格式通过示例代码介绍的很详细,需要的朋友参考下吧

什么是模块,什么是库包

模块(module):就是一个.py文件,里面用来存放一些变量和函数,便于在其他的.py文件中import
库包(package):库包是更大的组织单位,用来组织管理多个模块文件。
import用来导入模块module
from用来从模块中导入函数(部分函数或者全部函数)

import的使用

import 模块 [as 别名]         # 导入单模块
import 包.[N包].模块          # 导入包中的模块

注意:
   import导入最后一个必须是模块,而不能以库包结尾
(1)导入单模块文件,在导入的时候,会从上到下执行模块中的代码
(2)导入包中的模块,首先会执行包中的__init__.py文件
(3)导入包.包.模块, 会执行各个库包下的__init__.py文件
(4)如果是导入包.包,这样会报错,因为import的最后不能以库包结尾。

from的使用

from 包.[..包] import 模块
from 包.模块  import 方法
from 模块 import 方法

模式1

import 模块名1 [as 别名1], 模块名2 [as 别名2],…

说明:1)将整个模块导入;
     2[as 别名]部分可无,取别名简化引用; 
     3)使用导入模块中的成员(类,函数,变量)的格式:模块名[或别名].成员
        成员包括属性(变量)或函数,类

模式2

from 模块名 import 成员名1 [as 别名1],成员名2 [as 别名2],…

说明:1)导入模块中的某个成员;
     2)可以用*代表所有成员,如from 模块名 import *
        一般不建议这么写,因为模块中的成员有很多,我们也不会全部都用到,
        如果用不到,就是浪费,而且还占用资源。
        所以一般的操作是:用到什么,就导入什么,比如from functools import reduce

若导入包中模块,将上面语法中的模块名改为 包名.模块名

提示:import xxx和from xxx import yyy,两者的区别在于:
    import xxx,需要通过xxx.yyy的方式使用导入模块中的变量、函数、类等。
    from xxx import yyy,可以直接以yyy调用。
 import turtle
 turtle.circle(100)
 
 import turtle as t
 a.circle(100)
 
 from turtle import *
 cricle(100)
 
import module_name,即import后面之际跟模块名字,python解释器会在2个地方去寻找这个模块。
第一个是在sys.path中,os模块就是在sys.path中的,一般安装的python库的目录都可以在sys.path中找到
第二个是执行文件所在的目录。

模块module

模块首先是文件。
我们都知道的,.py文件是模块,但是除此之外.pyo .pyc  .pyd .pyw .dil等文件也是模块。
但是python初学者几乎用不到。

module中可以定义类,函数,变量,也可以包含可以执行的代码。
module的来源有3种:
<1>python的内置模块(标准库)
<2>第三方模块
<3>自定义模块

包package

为了避免模块名子的冲突,python引入了按照目录组织模块的方法,称之为包package.
包是有多个模块的文件夹。
在python3.3之前,一个目录如果想被当作package被导入,必须包含__init__.py文件,而在python3.3及以后的python版本中,__init__.py文件可以不再需要。
包含__init__.py文件的包,该文件可以是空的,既然是空文件,存在即可,相当于是一个标记。

绝对导入和相对导入

假设我们的项目project的结构是以下这样的

图片.png

<1>绝对导入

绝对路径要求我们必须从最顶层的文件夹开始,为每个包或每个模块提供出完整详细的导入路径。如:
from package1 import mudule1
from package1.module2  import Fx
from package2  import Cx
from package2.subpackage1.module5 import Fy

<2>相对导入

但我们使用相对导入的时候,我们需要给出相对于当前位置,想导入资源所在的位置。
相对导入,又分为隐士相对导入和显示相对导入。
比如我们想在package2/module3.py中引用module4模块,我们可以这么写
import module4 # 隐式相对导入,以为是在同一个目录下,所以可以直接导入
from . import module4 # 显式相对导入  ,也可以用.表示当前目录
from package2 import module4 # 绝对导入

代码中.表示当前文件所在的目录,如果是..就表示该目录的上一层目录,三个.、四个.依次类推。可以看出,隐式相对导入相比于显式相对导入无非就是隐含了当前目录这个条件,不过这样会容易引起混乱,所以在PEP 328的时候被正式淘汰,毕竟“Explicit is better than implicit”。

想在package2/module3.py中导入class Cx和function Fy,可以这么写
# package2/module3.py

import Cx # 隐式相对导入 因为class Cx被写在了__init__.py中,所以在module3.py中可以直接import Cx

from . import Cx # 显式相对导入

from .subpackage1.module5 import Fy

#############################
#############################
#############################

1/调用python内置的库包

比如 import json 
比如 import sys
像这些内置的库包,直接在.py文件中 import 就可以了,因为这些内置的库包都已经添加到环境变量中了。

2/第三方包

如果是 import 第三方包,则需要先安装再import 
安装完之后,也会自动得添加到环境变量中,也是可以直接导入的。

3/import 自定义的包

下面是一个python项目的结构
 test
 ----t1.py
 ----t2.py
 
 ----test1
 --------test111.py
 
 ----test2
 --------test222.py
 

<1>同一个目录中的模块之间的调用:t1.py中调用t2.py中的东西

   因为t1.py和t2.py是在同一个目录下,及二者都是在test这个目录下的。
   所以直接:
   # 直接导入模块,然后使用模块中的函数
   import t2
   t2.func()
   

<2>上级目录调用下级目录,需在下级目录中创建__init__.py文件,该文件可以什么都不写。

   比如t1.py调用 test1 目录中的test111.py模块,则需要在test1目录中创建__init__.py文件。
   from test1.test111 import * 
   func() # 直接使用test111.py中的各个函数
   
   或者写成:
   import test1.test111
   test111.func()
   
   以上2种写法都可以
   注意:
      上级调用下级的时候,不用写import sys sys.path.append()或者sys.path.insert()等
      因为上级牛逼啊,所以不用写。
      但是如果是下级调用上级的,就需要写了
      
   但是如果是下级去调用上级的话,就必须是import sys了
   就算是同级目录中的文件调用,也是需要import sys的。
   

<3>同一级别目录之间文件的调用,被调用文件所在的目录下需要创建__init__.py文件

  比如test2目录下的test222.py文件要去调用test1目录下的test111.py文件,
  因为test1和test2是同一级别的目录,所以test222.py模块去调用test111.py模块是同级目录下文件之间的调用
  
  import sys
  sys.path.append("..")
  import test1.test111
  test1.test111.func()
  
  
  或者是:
  import sys
  sys.path.append("..")
  from test1.test111 import * 
  func()
  

<4>调用上级目录的文件

  ⾸先 sys.path 的作⽤是:
     当使⽤import语句导⼊模块时,解释器会搜索当前模块所在⽬录以及sys.path指定的路径去找需要import的模块
     所以改变思路,直接把上级⽬录加到 sys.path ⾥
     import sys
     sys.path.append('../')
     from fatherdirname import xxx

如何控制模块中的函数是否可以让别人调用

 如果只想将模块内的部分函数开放给外界调用,则可以在模块头部加上
# dataset.py
__all__=["fun1","fun2","fun3"]
def fun1():
   pass
def fun2():
   pass
def fun3():
   pass
def fun4():
   pass
def fun5():
   pass
...

   这样,只有func1,func2,func3函数可以被被人调用,func4,func5则不能被别人调用。