odoo后台启动过程分析之一

odoo后台启动过程分析之一

1、odoo-bin

#!/usr/bin/env python3# set server timezone in UTC before time module imported
__import__('os').environ['TZ'] = 'UTC'
import odooif __name__ == "__main__":odoo.cli.main()

这个odoo-bin是一切的起点。 代码很简单

第一步:先设置了时区

熟悉odoo的都知道,odoo的运行环境都是UTC,也就是0时区

第二步: 引入odoo包

odoo包

这里看上去只是导入了一个包,但是干了不少事,import odoo就会去执行odoo目录下的init文件,看看这个文件都干了哪些事

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.""" OpenERP core library."""#----------------------------------------------------------
# odoo must be a namespace package for odoo.addons to become one too
# https://packaging.python.org/guides/packaging-namespace-packages/
#----------------------------------------------------------
import pkgutil
import os.path
__path__ = [os.path.abspath(path)for path in pkgutil.extend_path(__path__, __name__)
]import sys
assert sys.version_info > (3, 7), "Outdated python version detected, Odoo requires Python >= 3.7 to run."#----------------------------------------------------------
# Running mode flags (gevent, prefork)
#----------------------------------------------------------
# Is the server running with gevent.
evented = False
if len(sys.argv) > 1 and sys.argv[1] == 'gevent':sys.argv.remove('gevent')import gevent.monkeyimport psycopg2from gevent.socket import wait_read, wait_writegevent.monkey.patch_all()def gevent_wait_callback(conn, timeout=None):"""A wait callback useful to allow gevent to work with Psycopg."""# Copyright (C) 2010-2012 Daniele Varrazzo <daniele.varrazzo@gmail.com># This function is borrowed from psycogreen module which is licensed# under the BSD license (see in odoo/debian/copyright)while 1:state = conn.poll()if state == psycopg2.extensions.POLL_OK:breakelif state == psycopg2.extensions.POLL_READ:wait_read(conn.fileno(), timeout=timeout)elif state == psycopg2.extensions.POLL_WRITE:wait_write(conn.fileno(), timeout=timeout)else:raise psycopg2.OperationalError("Bad result from poll: %r" % state)psycopg2.extensions.set_wait_callback(gevent_wait_callback)evented = True# Is the server running in prefork mode (e.g. behind Gunicorn).
# If this is True, the processes have to communicate some events,
# e.g. database update or cache invalidation. Each process has also
# its own copy of the data structure and we don't need to care about
# locks between threads.
multi_process = False#----------------------------------------------------------
# libc UTC hack
#----------------------------------------------------------
# Make sure the OpenERP server runs in UTC.
import os
os.environ['TZ'] = 'UTC' # Set the timezone
import time
if hasattr(time, 'tzset'):time.tzset()#----------------------------------------------------------
# PyPDF2 hack
# ensure that zlib does not throw error -5 when decompressing
# because some pdf won't fit into allocated memory
# https://docs.python.org/3/library/zlib.html#zlib.decompressobj
# ----------------------------------------------------------
import PyPDF2try:import zlibdef _decompress(data):zobj = zlib.decompressobj()return zobj.decompress(data)PyPDF2.filters.decompress = _decompress
except ImportError:pass # no fix required#----------------------------------------------------------
# Shortcuts
#----------------------------------------------------------
# The hard-coded super-user id (a.k.a. administrator, or root user).
SUPERUSER_ID = 1def registry(database_name=None):"""Return the model registry for the given database, or the database mentionedon the current thread. If the registry does not exist yet, it is created onthe fly."""if database_name is None:import threadingdatabase_name = threading.current_thread().dbnamereturn modules.registry.Registry(database_name)#----------------------------------------------------------
# Imports
#----------------------------------------------------------
from . import upgrade  # this namespace must be imported first
from . import addons
from . import conf
from . import loglevels
from . import modules
from . import netsvc
from . import osv
from . import release
from . import service
from . import sql_db
from . import tools#----------------------------------------------------------
# Model classes, fields, api decorators, and translations
#----------------------------------------------------------
from . import models
from . import fields
from . import api
from odoo.tools.translate import _, _lt
from odoo.fields import Command#----------------------------------------------------------
# Other imports, which may require stuff from above
#----------------------------------------------------------
from . import cli
from . import http

从这段代码中可以得出几点:

  1. python版本必须要3.7以上
  2. 判断是否运行在gevent模式 这是啥模式?
  3. 再次设置了时区为UTC
  4. 导入了PyPDF2和zlib, 这俩玩意干嘛的?
  5. 硬编码超级用户SUPERUSER_ID = 1
  6. 定义了一个函数registry,返回指定数据库的model 注册表,这是个核心概念,最关键的是这句return modules.registry.Registry(database_name)

然后就是导入包和模块,大概分了三类

1、odoo的核心包

2、ORM有关的,翻译有关的

3、其他的cli http, cli是跟脚手架有关的命令, http是web服务。

cli包

我们来关注一下cli这个包,这个包包含了脚手架的所有命令。

#cli/__init__.py
import logging
import sys
import osimport odoofrom .command import Command, mainfrom . import cloc
from . import deploy
from . import scaffold
from . import server
from . import shell
from . import start
from . import populate
from . import tsconfig
from . import neutralize
from . import genproxytoken
from . import db

注意这一句

from .command import Command, main

cloc、deploy、scaffold…这些类都继承了Command这个类, 而这个Command类有点意思,看看它的定义

class Command:name = Nonedef __init_subclass__(cls):cls.name = cls.name or cls.__name__.lower()commands[cls.name] = cls
# __init_subclass__ 这个系统函数是从python3.6才有的
# 所有继承这个类的子类在定义的时候都会执行这个函数,而这个Command类就干了两件事,定义了一个name属性,以及收集所有的子类放到commands这个字典中去。
# 字典的key是小写的子类名,而value是子类对象。

当导入了所有的Command子类后, 也就等于收集了所有odoo-bin 支持的指令,现在可以执行main函数了。

第三步:执行了odoo.cli.main() 函数

def main():args = sys.argv[1:]# The only shared option is '--addons-path=' needed to discover additional# commands from modulesif len(args) > 1 and args[0].startswith('--addons-path=') and not args[1].startswith("-"):# parse only the addons-path, do not setup the logger...odoo.tools.config._parse_config([args[0]])args = args[1:]# Default legacy commandcommand = "server"# TODO: find a way to properly discover addons subcommands without importing the world# Subcommand discoveryif len(args) and not args[0].startswith("-"):logging.disable(logging.CRITICAL)initialize_sys_path()for module in get_modules():if (Path(get_module_path(module)) / 'cli').is_dir():__import__('odoo.addons.' + module)logging.disable(logging.NOTSET)command = args[0]args = args[1:]if command in commands:o = commands[command]()o.run(args)else:sys.exit('Unknown command %r' % (command,))

第一行先把odoo-bin本身从参数列表中去掉了,然后判断第二个参数是不是–addons-path ,如果是的话调用config相关函数处理

然后设置默认的指令是server, 当然这个值可能会被覆盖

如果接下来的参数不以-开头,说明command是有指定的,

        command = args[0]    # 取了第一个参数覆盖了之前设置的serverargs = args[1:]      # 剩下的就是指令的参数了

如果指令在上文收集的命令字典中, 那么就new一个子类对象o,然后调用子类的run函数,并且把args作为参数传过去。否则程序退出。

    if command in commands:o = commands[command]()o.run(args)else:sys.exit('Unknown command %r' % (command,))

分析到这里,我们看到了odoo-bin这个脚手架是怎么实现的了。 重点是

Command这个父类,以及它里面的__init_subclass__这个函数。

后面我们分析一下常用的两个指令 server和scaffold。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/132893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LangChain+LLM实战---Midjourney(v5.1) Prompt深度剖析

原文&#xff1a;Anatomy of Midjourney Promps: In-Depth Study for effective Prompting Strategies — V5.1 examples 作者&#xff1a;Michael King 你是否曾经发现自己盯着Midjourney的空白画布&#xff0c;手指悬停在键盘上&#xff0c;让我问自己&#xff1a;“我应该…

kafka问题汇总

报错1&#xff1a; 解决方式 1、停止docker服务   输入如下命令停止docker服务 systemctl stop docker 或者service docker stop1   停止成功的话&#xff0c;再输入docker ps 就会提示出下边的话&#xff1a; Cannot connect to the Docker daemon. Is the docker daem…

方案分享:F5机器人防御助企业应对复杂攻击

企业是Bot攻击者的目标&#xff0c;网络犯罪分子会不断调整他们的攻击&#xff0c;来攻破愈发成熟的Bot防护&#xff0c;这使企业安全团队时刻处于紧张状态。如果不能有效地管理Bot&#xff0c;应用性能、客户体验和业务都会被影响&#xff0c;但在尝试阻止这些攻击时&#xff…

【PTE-day02 sqlmap操作】

1、sqlmap简介 🍇sqlmap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL进行SQL注入。目前支持的数据库有MySql、Oracle、Access、PostageSQL、SQL Server、IBM DB2、SQLite、Firebird、Sybase和SAP MaxDB等. Sqlmap采用了以下5种独特的SQL注入技术 (1)…

k8s service

文章目录 Service 基础概念Service 类型&#xff1a;Service 的工作流程&#xff1a;东西流量&#xff0c;南北流量NodePortLoadBalancer Service 基础概念 在 Kubernetes&#xff08;K8s&#xff09;中&#xff0c;Service 是一个抽象的概念&#xff0c;表示一个应用程序的逻…

计算机毕设 基于大数据的服务器数据分析与可视化系统 -python 可视化 大数据

文章目录 0 前言1 课题背景2 实现效果3 数据收集分析过程**总体框架图****kafka 创建日志主题****flume 收集日志写到 kafka****python 读取 kafka 实时处理****数据分析可视化** 4 Flask框架5 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&a…

【docker windows安装】

参考 博客1、博客2、博客3.

fio数据整理之二

fio数据简单抓取 上文我们完成了一些fio output数据的简单抓取&#xff0c;本文将针对抓取的数据做进一步的处理&#xff0c;输出到表格之中&#xff0c;方便我们查看&#xff0c;统计结果。 本文先使用最简单的方法创建csv档案 我们现有个基本认知&#xff0c;在csv档案中&am…

【星海出品】VUE(六)

插槽Slots 传递属性 attribute App,vue <script> import SlotsBase from "./components/SlotsBase.vue" import SlotsTow from "./components/SlotsTow.vue" export default {components:{SlotsBase,SlotsTow},data(){return{message: "父集 m…

Corel VideoStudio 会声会影2024剪辑中间的视频怎么删 剪辑中音乐太长怎么办

我很喜欢视频剪辑软件Corel VideoStudio 会声会影2024&#xff0c;因为它使用起来很有趣。它很容易使用&#xff0c;但仍然给你很多功能和力量。视频剪辑软件Corel VideoStudio 会声会影2023让我与世界分享我的想法&#xff01;“这个产品的功能非常多&#xff0c;我几乎没有触…

flink1.15报错 processElement_split

flink sql 完整报错 Caused by: java.lang.NullPointerExceptionat StreamExecCalc$1148.processElement_split178(Unknown Source) ~[?:?]at StreamExecCalc$1148.processElement(Unknown Source) ~[?:?]at org.apache.flink.streaming.runtime.tasks.CopyingChainingOutp…

【MySQL数据库】 四

本文主要介绍了mysql数据库的几种常见的约束. 一.数据库约束 我们希望存储的数据是靠谱的,mysql提供一些机制来辅助我们自动的依赖程序对数据进行检查 . 这类查数据的机制,就是约束 一旦约束好了,后续在进行增 删 改的时候,mysql就会自动的对修改的数据做出检查,如果不符合…

openGauss学习笔记-116 openGauss 数据库管理-设置数据库审计-审计概述

文章目录 openGauss学习笔记-116 openGauss 数据库管理-设置数据库审计-审计概述116.1 背景信息116.2 操作步骤 openGauss学习笔记-116 openGauss 数据库管理-设置数据库审计-审计概述 116.1 背景信息 数据库安全对数据库系统来说至关重要。openGauss将用户对数据库的所有操作…

AWS:EC2实例创建步骤

创立步骤修改 播报 假如你现已准备好运用Amazon Web服务(AWS)&#xff0c;那么&#xff0c;至少有两种做法能够用来创立以及运用AWS。一种做法是运用AWS API(应用程序编程接口)调用。主张你在大多数情况下运用第二种做法, 即AWS办理操控台&#xff0c;亚马逊的基于web的界面。 …

服务器搭建:从零开始创建自己的Spring Boot应用【含登录、注册功能】

当然&#xff0c;你可以先按照IDEA搭建SSM框架【配置类、新手向】完成基础框架的搭建 步骤 1&#xff1a;设计并实现服务器端的用户数据库 在这个示例中&#xff0c;我们将使用MySQL数据库。首先&#xff0c;你需要安装MySQL并创建一个数据库以存储用户信息。以下是一些基本步…

后端工程化 | SpringBoot 知识点

文章目录 [SpringBoot] 后端工程化1 需求2 开发流程3 RequestController 类&#xff08;操作类&#xff09;3.1 简单参数&#xff08;形参名和请求参数名一致&#xff09;3.2 简单参数&#xff08;形参名和请求参数名不一致&#xff09;3.3 复杂实体参数3.4 数组参数3.5 集合参…

【从0到1开发一个网关】网关Mock功能的实现

文章目录 什么是Mock?如何实现Mock什么是Mock? Mock(模拟)是一种测试技术,用于创建虚拟对象来模拟真实对象的行为。Mock对象模拟了真实对象的行为,但是不依赖于真实对象的实现细节。它们可以在测试中替代真实对象,以便进行独立的单元测试。 需要使用Mock的原因包括以下几…

COOHOM通过采用亚马逊云科“专库专用”的方式,为云原生的构建提供稳定的数据支撑

全球化浪潮下&#xff0c;面对全球化业务发展带来的新需求与新挑战&#xff0c;越来越多的企业开启了云原生构建旅程&#xff0c;以推动业务系统快速迭代&#xff0c;为国际业务的拓展打下坚实的基础。COOHOM是杭州群核信息技术有限公司旗下的国际化品牌。为全球企业和个人提供…

《面向对象软件工程》笔记——1-2章

“学习不仅是一种必要&#xff0c;而且是一种愉快的活动。” - 尼尔阿姆斯特朗 文章目录 第一章 面向对象软件工程的范畴历史方面经济方面维护方面现代软件维护观点交付后维护的重要性 需求、分析和设计方面团队开发方面没有计划&#xff0c;测试&#xff0c;文档阶段的原因面向…

8-3、T型加减速单片机程序【51单片机控制步进电机-TB6600系列】

摘要&#xff1a;根据前两节内容&#xff0c;已完成所有计算工作&#xff0c;本节内容介绍具体单片机程序流程及代码 一、程序流程图 根据前两节文章内容可知&#xff0c;T型加减速的关键内容是运动类型的判断以及定时器初值的计算&#xff0c;在输出运动参数后即可判断出运动…