IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 4、命令行源码追踪-3-shell -> 正文阅读

[Python知识库]4、命令行源码追踪-3-shell

1、前言

1、我们执行 python manage.py shell 这个命令后,将会进入到和django的一个会话,就跟在命令行中输入 python 之后,将会进入到跟 python 的交互一样,这实际的效果大概类似于这样:

?2、handle 方法

1、django.core.management.commands.shell.py

2、下面为 Command 类中的 handle 方法

3、核心相当于执行 return getattr(self, 'python')(options)

def handle(self, **options):
    if options['command']:
        exec(options['command'], globals())
        return

    if sys.platform != 'win32' and not sys.stdin.isatty() and select.select([sys.stdin], [], [], 0)[0]:
        exec(sys.stdin.read(), globals())
        return

    # 未指定相关的 interface ,因此为默认
    # 1、self.shells: ['ipython', 'bpython', 'python']
    available_shells = [options['interface']] if options['interface'] else self.shells

    for shell in available_shells:
        try:
            # 2、当前会反射执行已有的 shell
            # 3、而实际我们使用的是 python,ipython、bpython均未安装
            return getattr(self, shell)(options)
        except ImportError:
            pass
    raise CommandError("Couldn't import {} interface.".format(shell))

4、从上述代码中的 getattr 可知,最后将执行当前类中的 python?方法

5、以下为 Command 类中的 python 方法

def python(self, options):
    import code
    imported_objects = {}

    if not options['no_startup']:
        for pythonrc in OrderedSet([os.environ.get("PYTHONSTARTUP"), os.path.expanduser('~/.pythonrc.py')]):
            if not pythonrc:
                continue
            if not os.path.isfile(pythonrc):
                continue
            with open(pythonrc) as handle:
                pythonrc_code = handle.read()
            try:
                exec(compile(pythonrc_code, pythonrc, 'exec'), imported_objects)
            except Exception:
                traceback.print_exc()
    try:
        hook = sys.__interactivehook__
    except AttributeError:
        pass
    else:
        try:
            hook()
        except Exception:
            print('Failed calling sys.__interactivehook__')
            traceback.print_exc()
    try:
        import readline
        import rlcompleter
        readline.set_completer(rlcompleter.Completer(imported_objects).complete)
    except ImportError:
        pass
    # 1、只是执行了这一段代码
    # 2、code 模块中的 interact 方法执行后将打来命令行模式
    code.interact(local=imported_objects)

6、做一下测试,关于code.interact() 方法以及参数的使用说明

?3、测试

1、直接在命令行输入 python manage.py shell,进入与django的交互模式,一些都很顺利,成功使用模型查询了数据

2、另一次测试,在命令行输入 python,同样导入模型类,看发生了什么

3、代码报错了-_-||。。

4、这与 python manage.py shell 进入的交互,中间缺少了什么会导致如此?

5、按照提示的_setup()函数,进去看一下具体的报错

?6、_setup() 函数如下,发现,当 settings_module 为 False 的时候,将会抛出异常

7、经过查看 manage.py 之后,发现 manage.py 中存在设置环境变量的代码如下

?8、现在已经发现了问题,则我们继续?

9、这次依然出现了异常,-_-||、、、

10、但是已经是不是同一个异常了,点进入之后检查到底是什么原因

11、从上述代码中可以看到当 apps_ready 为 False 的时候,将会抛出异常

12、而 self.apps_read 默认为 False (这里点一下就可以看到,不再截图)

13、分析:如果想要跳过这个异常,则 apps_ready 必须为 True 才可以,则我们需要找出是哪一段代码将 apps_ready 置为了 True

14、在 IDE 的帮助下,很快定位带了这个 self 方法,其代码如下

def populate(self, installed_apps=None):

    if self.ready:
        return
    with self._lock:
        if self.ready:
            return

        if self.loading:
            # Prevent reentrant calls to avoid running AppConfig.ready()
            # methods twice.
            raise RuntimeError("populate() isn't reentrant")
        self.loading = True

        # Phase 1: initialize app configs and import app modules.
        for entry in installed_apps:
            if isinstance(entry, AppConfig):
                app_config = entry
            else:
                app_config = AppConfig.create(entry)
            if app_config.label in self.app_configs:
                raise ImproperlyConfigured(
                    "Application labels aren't unique, "
                    "duplicates: %s" % app_config.label)

            self.app_configs[app_config.label] = app_config
            app_config.apps = self

        # Check for duplicate app names.
        counts = Counter(
            app_config.name for app_config in self.app_configs.values())
        duplicates = [
            name for name, count in counts.most_common() if count > 1]
        if duplicates:
            raise ImproperlyConfigured(
                "Application names aren't unique, "
                "duplicates: %s" % ", ".join(duplicates))
        
        # 1、此处将 apps_ready 置为 True
        self.apps_ready = True
        ... ...

15、已经找到了这个方法将 apps_ready 置为True,那么只剩下一件事,就是在哪里调用了这个方法

16、在 IDE 的帮助下,我们找到了调用该代码的位置,该代码存在 django 的 setup() 方法下

17、问题分析到此,如果想进入到与django的命令行交互,这里再调用 setup 方法应该就可以了,让我们再次尝试一下?

?18、终于成功了,在执行完上述步骤后,实现了与 python manage.py shell 相同的效果

4、总结

1、在 python manage.py shell 这个命令中,shell 规定进入交互模式

2、manage.py 中真正执行了就是 设置环境变量以及导入 setup 并执行,有兴趣可以打开 manage.py 找一下在哪里执行了 setup 方法

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:07:23  更:2022-09-04 01:07:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 15:22:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计