Python 入门 24 —— import 导入、 __name__、 __main__

除了内置对象,标准库对象和扩展库对象在使用前都需要用 import 导入。

一、导入模块

(1)基本语句:import 模块名 [as 模块别名]

导入模块后就可以使用模块中的类、函数、对象等东东了,不过在使用时要加上“模块名.”这个前缀。为了简化前缀,在导入时可以用“as 模块别名”的方式,给模块取个别名。不过取了别名之后,原名就失效了。例如:

import datetime
d = datetime.date.today()
t = datetime.datetime.now()
print(d,t)    # 2020-02-03     2020-02-03 11:35:20.937157

print(dir(datetime))    # 查看模块中的所有对象:['MAXYEAR',... 'tzinfo']
print(dir(datetime.date))    # 查看类中所有成员:['__add__',... 'weekday', 'year']

import datetime as dt    # 给datetime取个别名
d01 = dt.date.today()
t01 = dt.datetime.now()
print(d01,t01)    # 2020-02-03     2020-02-03 11:37:21.739067
d02 = datetime.date.today()    # 原名失效:NameError: name 'datetime' is not defined

(2)同时导入多个模块:import 模块1名 [as 模块1别名], 模块2名 [as 模块2别名], …
例如:

import os, sys , datetime as dt, math    # 同时导入 os、sys、datetime、math
print(dt.date.today(), math.ceil(2.98))    # 2020-02-03    3

二、导入模块中的对象

(1)基本语句:from 模块名 import 对象名 [as 对象别名]

这种方式导入的不是整个模块中的所有对象,而是指定的对象。通过这种方式导入的对象,在使用时,不需要加上“模块名.”这个前缀。当然,这也带来一个问题:在导入多个模块的情况下,如果有对象重名的现象,重名的对象会相互屏蔽。在导入时也可以给对象另取别名。例如:

from datetime import date    # 仅导入 date

print(date.today())    # 2020-02-03
print(datetime.date.today())    # 不要前缀:NameError: name 'datetime' is not defined
print(datetime.now())    # 没有导入:NameError: name 'datetime' is not defined

(2)同时导入多个对象:from 模块名 import 对象1名 [as 对象1别名], 对象2名 [as 对象2别名], …

例如:

from datetime import date as dd, datetime as tt
print(dd.today(), tt.now())    # 2020-02-03    2020-02-03 12:57:32.903249

(3)导入模块中的所有对象:from 模块名 import *

例如:

from datetime import *
print(date.today(), datetime.now())    # 2020-02-03 2020-02-03 12:59:41.594610

三、导入自定义的模块

导入自定义模块与导入标准库模块的语句是一样的,但因为标准库模块是系统自己存放的,且一般统一放在固定的目录中,所以,导入时一般不用考虑路径问题,而自定义的模块就不一样了,如果不弄清楚模块的存放目录,系统就会找不到模块文件,从而使导入失败。

在import 语句中是不可以指定模块所在目录的。例如: mport c:/mymod,这个语句是错误的。

1、当前目录

系统在导入模块时,首先在当前目录中查找模块文件。例如:在命令行窗口中,提示符为:D:\py>,则首先在 D:\py 目录中查找模块文件,找到了模块文件就立即导入。

2、sys.path 中列出的目录

系统如果在当前目录中没有找到模块文件,则在查看 sys.path 中列出的目录,然后按照前后顺序,在各个目录中查找,找到了就导入,找不到就抛出异常:ModuleNotFoundError。

(1)查看 sys.path 中已有哪些目录:print(sys.path)。

例如:

import sys
print(sys.path)    # ['D:\\py\\python38.zip', 'D:\\py']

(2)在 sys.path 目录列表的最后添加目录:sys.path.append(目录名)。

例如:

import sys
sys.path.append('D:\\aa')
sys.path.append('D:\\bb')
sys.path.append('D:\\cc')

print(sys.path)    # ['D:\\py\\python38.zip', 'D:\\py', 'D:\\aa', 'D:\\bb', 'D:\\cc']

(3)在 sys.path 目录列表的指定序号前插入目录:sys.path.insert(序号,目录名)

例如:

import sys;
sys.path.append('D:\\aa')
sys.path.insert(2,'D:\\dd')
sys.path.insert(0,'D:\\ee')

print(sys.path)    # ['D:\\ee', 'D:\\py\\python38.zip', 'D:\\py', 'D:\\dd', 'D:\\aa']

在设置好目录后,就可以导入自定义的模块了。例如:

建立文件:E:\testpy\py05.py ,内容如下:

class c01:pass
class c02:pass
def fun01():pass
def fun02():pass

导入 p05 模块:

import sys
sys.path.append('E:\\testpy')
import py05
print(dir(py05))
# ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__',
# '__package__', '__spec__', 'c01', 'c02', 'fun01', 'fun02']

print(sys.path)    # ['D:\\py\\python38.zip', 'D:\\py', 'E:\\testpy']

四、导入自定义包

假设有以下自定义的包和模块:

pybao(E:/testpy/)
    __init__.py
    baopy01.py
    baopy02.py
    pybao01
        __init__.py
    pybao02
        __init__.py
        baopy03.py
        baopy04.py
        pybao11
            __init__.py
            baopy05.py
        pybao12
            __init__.py
            baopy06.py
            baopy07.py
            baopy08.py
            baopy09.py

也就是说:
E:/testpy目录中有:pybao包
pybao包中有:pybao01包、pybao02包
pybao02包中有:pybao11包、pybao12包

(1)基本语句:import 包名

与导入自定义模块一样,导入自定义包也有一个定位问题。系统同样是先在当前目录中查找,找不到就查看 sys.path 中列出的目录,然后按照前后顺序,在各个目录中查找,再找不到就抛出异常。

“import 包名” 这一语句并不是将包中的所有模块和对象导入,它唯一的结果是促使包中的 “__ init__.py” 被执行。

例如:E:/testpy/pybao/init.py 的内容为:

print('This is __init__.py of pybao')
import sys
sys.path.append('E:\\testpy')

import pybao    # This is __init__.py of pybao

“__ init__.py”被执行之后,如果在这个文件中有导入的语句,则相应的模块和对象,就会被导入。例如:E:/testpy/pybao/__ init__.py 的内容为:

print('This is __init__.py of pybao')

import sys
sys.path.append('E:\\testpy\\pybao')
import baopy01,baopy02

以这种方式导入的模块,在引用时要加上“包名.”这个前缀,例如:

import sys
sys.path.append('E:\\testpy')
import pybao    # This is __init__.py of pybao
print(dir(pybao.baopy01))    # [... 'c11', 'c12', 'fun11', 'fun12']
print(dir(pybao.baopy02))    # [... 'c21', 'c22', 'fun21', 'fun22']

总之,“import 包名” 不会直接导入任何的模块和对象,只会触发包中的 __ init__.py 文件被执行。

(2)导入包中的包:import 大包名.小包名. …

在导入过程中,大包、小包中的 __ init__.py 文件的都会被执行。例如:

E:/testpy/pybao/__ init__.py 的内容为:

print('This is __init__.py of pybao')

E:/testpy/pybao02/__ init__.py 的内容为:

print('This is __ init__.py of pybao02')

E:/testpy/pybao12/__ init__.py 的内容为:

print('This is __init__.py of pybao12')

导入包:pybao12

import sys
sys.path.append('E:\\testpy')
import pybao.pybao02.pybao12
# 显示:
# This is __init__.py of pybao
# This is __init__.py of pybao02
# This is __init__.py of pybao12

(3)直接导入包中的模块:import 包名.模块名

在导入过程中,包中的 __ init__.py 文件的会先被执行,然后导入包。例如:

E:/testpy/pybao/init.py 的内容为:

print('This is __init__.py of pybao')

导入 pybao 包中的 baopy01.py 模块:

import sys
sys.path.append('E:\\testpy')

import pybao.baopy01    # This is __init__.py of pybao
print(dir(pybao.baopy01))    # [... 'c11', 'c12', 'fun11', 'fun12']

以这种方式导入的模块,在引用时也要加上“包名.”这个前缀,例如:

(4)直接导入包中的多个模块:from 包名 import *

这一语句不是直接导入包中的所有模块,而导入 “__ init__.py” 文件中, __ all__变量指定的模块。例如:

E:/testpy/pybao/pybao02/pybao12/init.py 的内容为:

print('This is __init__.py of pybao12')
__all__=[baopy05,baopy06]

导入pybao12的模块:

import sys
sys.path.append('E:\\testpy')

from pybao.pybao02.pybao12 import *
# 显示:
# This is __init__.py of pybao
# This is __init__.py of pybao02
# This is __init__.py of pybao12

print(dir(baopy05))    # [...  'c51', 'c52', 'fun51', 'fun52']
print(dir(baopy06))    # [...  'c61', 'c62', 'fun61', 'fun62']
print(dir(baopy08))    # [...  'c81', 'c82', 'fun81', 'fun82']
print(dir(baopy09))    # NameError: name 'baopy09' is not defined

以这种方式导入的模块,在引用时不需要 “包名.” 这个前缀。

五、 __ name__ 和 __ main__

模块被导入后,系统将它转化成“模块对象”,并且还会为模块对象缺省添加上一些数据成员。例如:
E:/testpy/py06.py 的内容为:

class c06:pass
import sys
sys.path.append('E:\\testpy')
import py06
print(dir(py06))
# 显示:
# ['__builtins__', '__cached__', '__doc__', '__file__',
# '__loader__', '__name__', '__package__', '__spec__', 'c06']

模块对象中有一个名为“ __ name__”的数据成员比较常用。当模块被直接执行时,系统将“模块对象”的 __ name__值置为“ __ main__”,当模块被导入后再直接执行时模块的 __ name__值置为“模块名”。例如:
E:/testpy/py06.py 的内容为:

class c06:pass;  print('py06 __name__:',__name__)
import sys
sys.path.append('E:\\testpy')

import py06    # py06 __name__: py06

print('my __name__:',__name__)    # my __name__: __main__

在实际编程中,经常通过 name 的值来判断一个模块是否处在被导入中,以此来避免一些语句在导入时被执行。例如:

if __name__ == '__main__':    # 当当前模块被导入时,以下这些语句不会被执行
    x = 100
    y = 200
    z = 300

———————————————— 本篇完 ————————————————

看完之后,麻烦您顺手点击下方 “点赞” 两个字给我点个赞吧 ^-^ , 谢谢您了。

如果您还能像我小学一年级班主任好老师那样,给我随心写上几句表扬或批评的话语,那真是感激不尽!

在我人生的道路上,有了您的鼓励和指导,我一定成长快快。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章