python编程基础(3):包、模块导入以及Django相关源代码

这两天在看django的源代码,对包/模块的导入部分还不是很熟悉,这边结合Django源码代码,做一下理解和记录~

目录:

1. 模块属性:__name__

2. 动态模块导入:__import__() 和 importlib.import_module()

3. 包的目录结构 & __init__.py文件

参考:

----------------------------------------------------------------------------------------------------------------------------------------------------------

1. __name__

在模块b中直接运行的输出结果可以知道,通过模块的__name__属性可以知道,哪个是被导入模块,哪个是直接运行模块

#文件 ./a.py
print("hello world")

#文件  ./b.py
import a
print(a.__name__)
print(b.__name__)

#在模块b中直接运行的输出结果如下:
hello world
a            #a为导入模块
__main__     #b为直接运行模块

2. __import__() 和 importlib.import_module()

二者都可实现动态导入模块(运行时导入),但__import__()只能导入第一级目录

__import__() :是系统提供的函数,而不是模块本身的属性方法

#文件 : b.py

__import__('sys')      #等价于 import sys
print(dir(b))          #使用dir()查看模块b本身并不存在__import__()方法

动态导入模块:importlib,在Django的源代码中多处看到:

示例一:当我们在做数据库迁移:python manage.py migrate;或者是启动服务器时:python manage.py runserver; 中间会经过很多步,到达load_command_class()这个函数。在django/core/management/commonds文件夹下,有很多.py文件,其中就有migrete.py和runserver.py; 数据库迁移和数据库的启动就是执行这两个文件里的Command()。

#文件  ./django/core/management/__init__.py
def load_command_class(app_name, name):    #app_name='django.core'  name=migrate/runserver
    module = import_module('%s.management.commands.%s' % (app_name, name)) 
    return module.Command()    #module='migrate.py'或者‘runserver’..其他.. 可实现动态变化

 示例二: 代码还没看,先跳过

#文件 ./django/core/management/manage.py

import_module('.management', app_config.name)
#import_module的语法定义
#def import_module(name, package=None)

3. 包的目录结构 & __init__.py文件

  • __init__是初始化模块,from-import 语句导入子包时需要用到它。 如果没有用到, 他们可以是空文件
'''
a.py
   __init__.py                #没有__init__.py,导入包的时候将报错
   b.py
        __init__.py           #没有__init__.py,导入包的时候将报错
        c.py
'''
  • 当我们导入包时,包下面的__init__.py会自动的被执行。 
# 文件 ./a.py
import pack_b.b     #输出两条语句: ‘pcak_b/b.py’    'pack_b.__init__.py'

#文件  ./pack_b/b/py
print('pack_b/b.py')

#文件  ./pack_b/__init__.py
print('pack_b.__init__.py')
  • Django源代码示例: 调用apps对象的get_app_configs()方法
#文件  ./django/core/management/__init__.py

from django.apps import apps   #开始以为导入的是apps模块,实际是apps对象,相当于from django.apps.registry import apps
def get_commands():
    #.....部分代码省略........
    for app_config in reversed(list(apps.get_app_configs())):    #调用apps对象的get_app_configs()方法
        path = os.path.join(app_config.path, 'management')
        commands.update({name: app_config.name for name in find_commands(path)})
    return commands

下一步,默认会先执行django.apps包下面的__init__.py,文件代码如下:

#文件  ./django/apps/__init__.py

from .config import AppConfig
from .registry import apps          #加了这一句,上一段代码from django.apps import apps

__all__ = ['AppConfig', 'apps']     # 用于from django.apps import *
最后,执行registry.py文件
#文件 ./django/apps/registry.py
class Apps:
#....部分代码省略.........
def get_app_configs(self):
    self.check_apps_ready()
    return self.app_configs.values()

apps = Apps(installed_apps=None)        #射击单例模式,再学习

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值