邮件系统 技术模块
This module optionally depends on ymlparsers
.
该模块可选地取决于ymlparsers
。
The source code you can found here. It is available as part of my AlexBerUtils s project.
您可以在此处找到源代码。 它是我的AlexBerUtils项目的一部分。
You can install AlexBerUtils from PyPi:
您可以从PyPi安装AlexBerUtils:
python3 -m pip install -U alex-ber-utils
You can optionally install some dependencies, such as jinja2. The easiest way is to run:
您可以选择安装一些依赖项,例如jinja2。 最简单的方法是运行:
python3 -m pip install alex-ber-utils[yml]
Note also that hiyapyco should be at least 0.4.16.
另请注意, hiyapyco至少应为0.4.16。
However, this is not strictly required.
但是,这不是严格要求的。
See here for more details explanation on how to install.
有关如何安装的更多详细说明,请参见此处。
简要描述;简介 (Brief description)
This module contains extensions of the logging handlers. See https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers for more details.
该模块包含日志记录处理程序的扩展。 有关更多详细信息,请参见https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers 。
alexber.utils.emails.OneMemoryHandler
is variant oflogging.handlers.MemoryHandler
. This handler aggregates log messages untilFINISHED
log-level is received or application is going to terminate abruptly and we have some log messages in the buffer. On such event all messages (in the current Thread) are aggregated to the singleEmailMessage
. This implementation is thread-safe.alexber.utils.emails.OneMemoryHandler
是logging.handlers.MemoryHandler
变体。 该处理程序聚合日志消息,直到收到FINISHED
日志级别或应用程序将突然终止,并且缓冲区中有一些日志消息为止。 在这种情况下,所有消息(在当前线程中)都将汇总到单个EmailMessage
。 此实现是线程安全的。alexber.utils.emails.SMTPHandler
is customization oflogging.handlers.SMTPHandler
. It’s purpose is to connect toSMTP
server and actually send the e-mail. Unlikelogging.handlers.SMTPHandler
this class expects forrecord.msg
to be builtEmailMessage
. You can also change use of underlineSMTP
class toSMTP_SSL
,LMTP,
etc. This implementation is thread-safe.alexber.utils.emails.SMTPHandler
是logging.handlers.SMTPHandler
自定义。 目的是连接到SMTP
服务器并实际发送电子邮件。 与logging.handlers.SMTPHandler
不同,此类希望将record.msg
构建为EmailMessage
。 您还可以将下划线SMTP
类的SMTP_SSL
更改为SMTP_SSL
,LMTP,
等。此实现是线程安全的。alexber.utils.emails.EmailStatus
— if contextmanager exits with exception (it fails), than e-mail will be send. All messages (in the current Thread) will be aggregated to one long e-mail.alexber.utils.emails.EmailStatus
—如果contextmanager异常退出(失败),则将发送电子邮件。 所有消息(在当前线程中)将汇总到一封长电子邮件中。alexber.utils.emails.initConfig
— this method reset some defaults. This method is idempotent.alexber.utils.emails.initConfig
此方法重置一些默认值。 该方法是幂等的。
Note:
注意:
emails module doesn’t require ymlparsers module (and it’s dependencies) to work correctly.
电邮 模块不需要ymlparsers 模块(及其依赖项)才能正常工作。
If you have ymlparsers module (and it’s dependencies) you can benefit with some extra features (see below).
如果您有ymlparsers 模块(及其依赖项),您可以从一些附加功能中受益(请参见下文)。
Note: All logging handlers are thread-safe. What does it mean in practice?
注意: 所有日志记录处理程序都是线程安全的。 实际上是什么意思?
The buffer that is used to hold email’s untill
FINISHED
log-level is received or calculation is going to terminate abruptly is managed per Thread.用于保留电子邮件的缓冲区,直到收到或计算完成日志级别
FINISHED
每个线程将管理将要突然终止的操作。If you have only
MainThread
it doesn’t matter for you.如果只有
MainThread
,那么对您来说就没有关系。If, for example, you’re using webpy web framework, you can send separate e-mail that we’ll describe your calculation per Request (webpy assign Thread per HTTP request; it also make reuse of Thread, but the old Thread should have empty buffer, use
EmailStatus
to ensure this).例如,如果您使用的是Webpy Web框架,则可以发送单独的电子邮件,我们将根据每个请求描述您的计算( webpy为每个HTTP请求分配线程;它还可以重用Thread,但是旧的Thread应该包含空缓冲区,请使用
EmailStatus
来确保这一点)。
代码示例 (Code Example)
Put the files above to the same directory as the script above. Configuration files, such as config.yml
should be also to the same directory.
将上面的文件与上面的脚本放在同一目录中。 配置文件,例如config.yml
应该也到同一个目录。
Note:
注意:
- It is not required to have multiple configuration file, 1 file may be enough. 不需要多个配置文件,一个文件可能就足够了。
You can also have no configuration file at all, and configure logger handler with
logging
API.您也可以完全没有配置文件,并使用
logging
API配置logging
记录处理程序。
Lines 1–7 some generic import.
第1至7行是一些通用导入。
On line 2 we’re importing fixabscwd() function . See Making relative path to file to work.
在第2行上,我们导入fixabscwd() 功能。 看到 使文件的相对路径起作用。
On lines 9–10 we set initial value to the logger
and emailLogger
.emailLogger
will be used to send e-mail. It will initialize with real value later, after parsing of configurations file will be done.
在第9-10行,我们将初始值设置为logger
和emailLogger
。 emailLogger
将用于发送电子邮件。 解析配置文件后,它将稍后使用实际值初始化。
On lines 12–14 we’re extending init_app_conf.conf
helper class, I’m adding some this example specific key to existing one.
在第12-14行中,我们扩展了init_app_conf.conf
帮助器类,在现有示例中添加了一些此示例特定的键。
On line 19 we have run()
function, it will simulate running Python Process with 1 e-mail with stages of the process generated.
在第19行,我们具有run()
函数,它将通过1封电子邮件模拟正在运行的Python进程,并生成该进程的各个阶段。
On line 29 we have _log_config()
function, this function will instantiate ((global) module level) logger
and emailLogger.
在第29行,我们具有_log_config()
函数,该函数将实例化((全局)模块级别) logger
和emailLogger.
On line 43 we have main()
function, that receives optional args parameter. It has default None value. If no explicit value is passed than sys.args will be used implicitly. This function can be called from another module.
在第43行,我们有main()
函数,该函数接收可选的args参数。 它具有默认的None值。 如果未传递任何显式值,则将隐式使用sys.args 。 可以从另一个模块调用此函数。
On lines 62–63 we have standard code snippet: if this module executes as __main__ (and not imported to another module), than after all methods and (global) module-level attributes will be defined we’re calling main() function.
在第62-63行上,我们有标准的代码片段:如果此模块以__main__身份执行(并且未导入到另一个模块),那么在定义了所有方法和(全局)模块级属性之后,我们将调用main()函数。
When this code is executed, after all methods and (global) module-level attributes are define, main() function is called with args=None.
执行此代码后,在定义所有方法和(全局)模块级属性后,将使用args = None调用main()函数。
On lines 44–46 I’m making temporary logger initialization, when all logs with level INFO and above are redirected to stderr, all warnings are redirected to stderr. This will be effective till we’ll parse log’s configuration and reinitialize logger. This is done, in order to see log’s output, especially warnings. See Integrating Python’s logging and warnings packages for more details.
在第44-46行上,我正在进行临时记录器初始化,当所有级别为INFO或更高级别的日志都重定向到stderr时,所有警告都重定向到stderr。 在我们解析日志的配置并重新初始化记录器之前,这将是有效的。 这样做是为了查看日志的输出,尤其是警告。 有关更多详细信息,请参见集成Python的日志记录和警告包。
On line 48 we makes relative path to file to work.
在第48行,我们创建了要工作的文件的相对路径。
On lines 50–53 we’re parsing configuration files. See My major init_app_conf module for details.
在第50–53行,我们正在解析配置文件。 有关详细信息,请参见我的主要init_app_conf模块。
On line 55 we’re passing it to _log_config() function. Their we’re poping general.log part from the dict config and we’re calling logging.config.dictConfig() to reinitialize logger. We’re initializing (global) module-level attributes logger
(standard logger) emailLogger
(this logger will be used to send e-mails; this has configuration in logger.emails
in configuration file above). At the end we’re pretty-print parsed configuration. Uncommented line uses ymlparsers.as_str() as convenient method to print logger configuration to the logger. Commented-out line us pretty-print pprint
module (it is available in standard Python). It has caveat, though.
在第55行,我们将其传递给_log_config()函数。 他们正在从dict配置中弹出general.log部分,并在调用logging.config.dictConfig()重新初始化记录器。 我们正在初始化(全局)模块级属性logger
(标准记录器) emailLogger
(该记录器将用于发送电子邮件;这在logger.emails
的配置文件中的logger.emails
中进行了配置)。 最后,我们进行了漂亮的解析配置配置。 未注释的行使用ymlparsers.as_str() 作为将记录器配置打印到记录器的便捷方法。 注释掉了我们漂亮的pprint
模块行(在标准Python中可用)。 它有警告,但是。
Note: Actual type is
OrderedDict
and notdict,
but it is mainly for historical reasons…注意:实际类型是
OrderedDict
而非dict,
但这主要是出于历史原因…Side note: Up to (not included) Python 3.6 the order in which key/value are stored was undefined. In Python 3.6 it was stated that this is implementation detail of CPython (and best practice is not to relay on this behavior). Started from Python 3.7 dictionary order is guaranteed to be insertion order.
旁注:直到(不包括)Python 3.6,键/值的存储顺序均未定义。 在Python 3.6中,有人说这是CPython的实现细节(并且最佳实践不是基于这种行为)。 从Python 3.7开始,字典顺序保证是插入顺序。
See https://stackoverflow.com/a/58676384/1137529 for the differences between
dict
andOrderedDict
.有关
dict
和OrderedDict
之间的差异,请参见https://stackoverflow.com/a/58676384/1137529 。
https://medium.com/analytics-vidhya/my-parser-module-429ed1457718
https://medium.com/analytics-vidhya/my-parser-module-429ed1457718
pprint
was written way before 3.6. In order to produce consistent result, it sorts out dict by key. I have found this unappropriated, I want to see the configuration in exact same order as it defined in the configuration file. In Python 3.8, however, you can specify sort_dicts=False
in order to disable this sorting functionality. So, if you’re using Python 3.8 or above this will also works.
pprint
是在3.6之前编写的。 为了产生一致的结果,它按键对字典进行排序。 我发现这是不适当的,我想查看与配置文件中定义的顺序完全相同的配置。 但是,在Python 3.8中,可以指定sort_dicts=False
来禁用此排序功能。 因此,如果您使用的是Python 3.8或更高版本,这也将适用。
On line 39 we just remove general.log from parsed result. You can change remove this line, if you want to keep log configuration.
在第39行,我们只是从解析结果中删除了general.log 。 如果要保留日志配置,可以更改删除此行。
On lines 56–57 we’re calling run() inside EmailStatus
context-manager function where actual business logic should be put. I will get back to EmailStatus
below.
在第56-57行,我们在EmailStatus
上下文管理器函数内调用run() , EmailStatus
函数应放置实际的业务逻辑。 我将在下面回到EmailStatus
。
On line 20 we’re logging “run()” message to regular log.
在第20行,我们将“ run()”消息记录到常规日志中。
On line 21 we’re buffering “Start-Python Process” message in our emailLogger
.
在第21行,我们在emailLogger
缓冲“ Start-Python Process”消息。
On line 22 we just get our application configuration for the usage in the application code.
在第22行,我们仅获得应用程序代码中用法的应用程序配置。
On lines 23–24 we’re simulating some computation, buffering in the emailLogger
our progress.
在第23–24行,我们正在模拟一些计算,将我们的进度缓冲在emailLogger
。
On line 26 we’re buffering “Done Successfully — Python Process” message in our emailLogger
.
在第26行,我们在emailLogger
缓冲“成功完成emailLogger
处理”消息。
If no exception was thrown during code execution, when the code will exit from
EmailStatus
context-manager all buffered messages insideemailLogger
will be aggregated to 1 e-mail message with subject‘Python Process Status : {{status}}’
where status will be substituted withDone
(seesuccessargs
).如果没有异常是在代码执行期间抛出,当代码将从退出
EmailStatus
上下文管理器的所有缓冲的消息内emailLogger
将汇总为1的电子邮件与主题'Python Process Status : {{status}}'
,其中的状态将是用Done
替代(请参阅successargs
)。If exception will occur before line 56, before
EmailStatus
context-manager, no e-mail will be send.如果异常将在第56行之前发生在
EmailStatus
上下文管理器之前,则不会发送任何电子邮件。If exception will occur inside
run()
method than all buffered messages insideemailLogger
will be aggregated to 1 e-mail message with subject‘Python Process Status : {{status}}’
where status will be substituted withFailed
(seesuccessargs
). Also exception with stack-trace will be forwarded to regularlogger
(if provided; it is provided in this example).如果
run()
方法内部发生异常,则emailLogger
内部的所有缓冲消息将被汇总为1条主题为'Python Process Status : {{status}}'
的电子邮件,其中状态将替换为Failed
(请参见successargs
)。 堆栈跟踪的异常也将转发到常规logger
(如果提供;此示例中提供)。
Let’s start from EmailStatus
context-manager. This context-manager is technically optional, but I’m strongly encourage you to use it.
让我们从EmailStatus
上下文管理器开始。 从技术上讲,此上下文管理器是可选的,但我强烈建议您使用它。
All messages (in the current Thread) will be aggregated to one long e-mail with the subject described in OneMemoryHandler.get_subject()
method. (see also below).
所有消息(在当前线程中)将与OneMemoryHandler.get_subject()
方法中描述的主题聚合到一封长电子邮件中。 (另请参见下文)。
Note: If, for example, you’re using webpy web framework, you can send separate e-mail that we’ll describe your calculation per Request, webpy assign Thread per HTTP request; it also make reuse of Thread, but the old Thread should have empty buffer, use EmailStatus
to ensure this. If you don’t use EmailStatus
you can have Thread with buffered e-mail from previous request if exception occurred and you didn’t flush the buffer, that is bug. Theoretically, you can do it manually, I will describe this way below, but this way is error-prone.
注意:例如,如果您使用的是Webpy Web框架,则可以发送单独的电子邮件,我们将根据请求描述您的计算方式,Webpy会为每个HTTP请求分配线程; 它还可以重用Thread,但是旧的Thread应该具有空缓冲区,请使用EmailStatus
来确保这一点。 如果不使用EmailStatus
,则可以在发生异常并且没有刷新缓冲区的情况下使Thread带有来自先前请求的缓冲电子邮件。 从理论上讲,您可以手动进行操作,我将在下面描述这种方式,但是这种方式容易出错。
You can have subject of the e-mails without place holders, for example, ‘Aggregates log from the Demo application’.
您可以使电子邮件主题不带占位符,例如,“来自演示应用程序的汇总日志”。
Below, is example of customizable e-mails message.
下面是可自定义电子邮件的示例。
‘status’
is place holder in the subject of the e-mail. As in our case ‘My Process Status : {{status}}’.
'status'
是电子邮件主题中的占位符。 如我们的案例“我的流程状态:{{status}}”。
In this case the same subject of the e-mail will be used whether the code-block finish successfully or with failure.
在这种情况下,无论代码块成功完成还是失败,都将使用电子邮件的同一主题。
If you want to change delimiters used to indicate variable declaration inside template, see docstring of the OneMemoryHandler.get_subject()
method.
如果要更改用于指示模板内部变量声明的定界符,请参见OneMemoryHandler.get_subject()
方法的docstring。
emailLogger
: configured emailLogger. See above.
emailLogger
:已配置的emailLogger。 往上看。
faildargs
: variable resolution for e-mail’s subject on failure. Optional. Expected to be dict with variable substitution.
faildargs
:失败时电子邮件主题的可变分辨率。 可选的。 预期将与变量替换一起使用。
successargs
: variable resolution for e-mail’s subject on success. Optional. Expected to be dict with variable substitution.
successargs
:成功的电子邮件主题的可变分辨率。 可选的。 预期将与变量替换一起使用。
logger
: logger ot used if exception was thrown from the code. It will be used in addition to emailLogger. Optional.
logger
:如果代码中抛出异常,则使用logger。 除emailLogger外,还将使用它。 可选的。
successkwargs
: to be send to the emailLogger
’s kwargs param on success. Optional.
successkwargs
:成功时发送到emailLogger
的kwargs参数。 可选的。
faildkwargs
: to be send to the emailLogger
’s kwargs param on failure. Optional.
faildkwargs
:失败时发送到emailLogger
的kwargs参数。 可选的。
Note: It is better to use EmailStatus
context-manager even in single threaded application. If you chose not to, care should be taken to send appropriate message.
注意:即使在单线程应用程序中,最好也使用EmailStatus
上下文管理器。 如果您选择不这样做,则应注意发送适当的消息。
Now, let’s look onalexber.utils.emails.SMTPHandler.
This is customization of logging.handlers.SMTPHandler
. It’s purpose is to connect to SMTP
server and actually send the e-mail. This implementation is thread-safe.
现在,让我们看一下alexber.utils.emails.SMTPHandler.
这是logging.handlers.SMTPHandler
自定义。 目的是连接到SMTP
服务器并实际发送电子邮件。 此实现是线程安全的。
Note:
注意:
This class’s
__init_()
_receives additional parametersmtpclsname
that can besmtplib.SMTP, smtplib.SMTP_SSL
,smtplib.LMTP
, or any another class that will be used insteat of defaultSMTP
. You can supply it asstr
or as actual instance.此类的
__init_()
_接收其他参数smtpclsname
,它们可以是smtplib.SMTP, smtplib.SMTP_SSL
,smtplib.LMTP
或将用于默认SMTP
任何其他类。 您可以提供它作为str
或作为实际实例。emit()
method is overridden. This class expects forrecord.msg
to have fully constructedEmailMessage
, it is not constructed here.emit()
方法被覆盖。 此类期望record.msg
具有完全构造的EmailMessage
,此处未构造。
Now, let’s look on alexber.utils.emails.OneMemoryHandler.
This is variant of logging.handlers.MemoryHandler
. This handler aggregates log messages until FINISHED
log-level is received or application is going to terminate abruptly and we have some log messages in the buffer. This implementation is thread-safe.
现在,让我们看一下alexber.utils.emails.OneMemoryHandler.
这是logging.handlers.MemoryHandler
变体。 该处理程序聚合日志消息,直到收到FINISHED
日志级别或应用程序将突然终止,并且缓冲区中有一些日志消息为止。 此实现是线程安全的。
It is intended to configure first your emailLogger
with OneMemoryHandler
(together with SMTPHandler
).
它旨在首先使用OneMemoryHandler
(以及SMTPHandler
)配置您的emailLogger
。
The configuration above is equivalent to the following one:
上面的配置等同于以下配置:
Now, let’s go over some implementation details of alexber.utils.emails.OneMemoryHandler.
现在,让我们看一下alexber.utils.emails.OneMemoryHandler.
一些实现细节alexber.utils.emails.OneMemoryHandler.
All basic machinery are in alexber.utils.emails.BaseOneMemoryHandler
. OneMemoryHandler
inherit from BaseOneMemoryHandler
.
所有基本机制都位于alexber.utils.emails.BaseOneMemoryHandler
。 OneMemoryHandler
继承自BaseOneMemoryHandler
。
So, let’s go over BaseOneMemoryHandler
first.
因此,让我们先BaseOneMemoryHandler
。
BaseOneMemoryHandler
extends directly logging.handlers.MemoryHandler
.
BaseOneMemoryHandler
直接扩展logging.handlers.MemoryHandler
。
This implementation is thread-safe. Each Thread aggregates it’s own buffer of the log messages.
此实现是线程安全的。 每个线程都会聚合自己的日志消息缓冲区。
Quote from it’s docstring of logging.handlers.MemoryHandler
引用来自logging.handlers.MemoryHandler
的文档字符串
A handler class which buffers logging records in memory, periodically flushing them to a target handler. Flushing occurs whenever the buffer is full, or when an event of a certain severity or greater is seen.
处理程序类,用于在内存中缓冲日志记录,并定期将其刷新到目标处理程序。 只要缓冲区已满,或者看到某种严重程度或更严重的事件,就会发生刷新。
Note: buffer that is used is stored as threadlocal var.
注意:使用的缓冲区存储为threadlocal var。
This makes this module usable in the webpy web framework. You can send separate e-mail that we’ll describe your calculation per Request (webpy assign Thread per HTTP request).
这使得该模块可在webpy Web框架中使用。 您可以发送单独的电子邮件,我们将根据每个请求描述您的计算(每个HTTP请求由webpy分配线程)。
Note: Main method is:
注意:主要方法是:
create_one_record()
method is responsible to construct EmailMessage
.
create_one_record()
方法负责构造EmailMessage
。
Now, let’s look back on alexber.utils.emails.OneMemoryHandler.
It extends BaseOneMemoryHandler
. This handler aggregates log messages until FINISHED
log-level is received or application is going to terminate abruptly and we have some log messages in the buffer. This implementation is thread-safe.
现在,让我们回顾一下alexber.utils.emails.OneMemoryHandler.
它扩展了BaseOneMemoryHandler
。 该处理程序聚合日志消息,直到收到FINISHED
日志级别或应用程序将突然终止,并且缓冲区中有一些日志消息为止。 此实现是线程安全的。
On such event all messages (in the current Thread
) are aggregated to the single EmailMessage
. The subject of the EmailMessage is determined by get_subject()
method (see below).
在这种情况下,所有消息(在当前Thread
)都将汇总到单个EmailMessage
。 EmailMessage的主题由get_subject()
方法确定(请参见下文)。
Note: There are cases on which FINISHED
log-level is not received, but we know that application is going to terminate abruptly and we did aggregated some messages. See calc_abrupt_vars()
below.
注意:在某些情况下,未收到FINISHED
日志级别,但是我们知道应用程序将突然终止,并且我们汇总了一些消息。 请参阅下面的calc_abrupt_vars()
。
On such a cases we will send EmailMessage
as if FINISHED
log-level was received, but using abruptvars
field that was set in the constructor in calc_abrupt_vars()
method.
在这样的情况下,我们将发送EmailMessage
仿佛FINISHED
收到数级,但使用abruptvars
这是在构造函数中设置场calc_abrupt_vars()
方法。
If you want to change delimiters used to indicate variable declaration inside template, see get_subject()
method below.
如果要更改用于指示模板内部变量声明的定界符,请参见下面的get_subject()
方法。
alexber.utils.emails.OneMemoryHandler
has the following methods/class fields:
alexber.utils.emails.OneMemoryHandler
具有以下方法/类字段:
DEFAULT_ABRUPT_VARS
— class field with initial value{‘status’: ‘Finished Abruptly’}
. This value will be used to create subject of the e-mail message, when no variable was supplied — that is we have going to terminate abruptly and we did aggregated some messages. This is the default value forabruptvars
field.DEFAULT_ABRUPT_VARS
—初始值为{'status': 'Finished Abruptly'}
类字段。 当未提供任何变量时,此值将用于创建电子邮件的主题-也就是说,我们将突然终止,并且确实汇总了一些消息。 这是abruptvars
字段的默认值。calc_msg_params()
— basically this method responsible to useabruptvars
field untill we didn’t log messages withFINISHED
log-level.calc_msg_params()
—基本上,此方法负责使用abruptvars
字段,直到我们未使用FINISHED
日志级别记录消息。calc_abrupt_vars()
You can override this method.calc_abrupt_vars()
您可以重写此方法。
If your subject doesn’t contains place holders, for example, Aggregates log from the Demo application
, there is no need to override this method.
如果您的主题不包含占位符,例如Aggregates log from the Demo application
,则无需覆盖此方法。
There are alternatives though to change default behaviour of this method (see below).
尽管有其他方法可以更改此方法的默认行为(请参见下文)。
This method need to define self.abruptvars
field.
此方法需要定义self.abruptvars
字段。
If your application is stopped abruptly (for example, by SIGINT
) and your buffer (in the current Thread
) has some messages, logging system at shutdown will flush and close all handlers, so the buffer without message with log-level FINISHED
(and hence without variable substitution kwargs) will be flushed.
如果您的应用程序突然停止(例如,通过SIGINT
停止)并且您的缓冲区(在当前Thread
)具有一些消息,则关闭时的日志记录系统将刷新并关闭所有处理程序,因此没有消息的缓冲区的日志级别为FINISHED
(因此)没有变量替换的kwargs)将被刷新。
self.abruptvars
will be used instead.
self.abruptvars
将代替使用。
It is recommended to use EmailStatus
context manager in order to avoid this.
建议避免使用EmailStatus
上下文管理器。
The default implementation checks if abruptvars
kwargs was supplied in constructor. If it did, it will be used put as self.abruptvars
. If it doesn’t DEFAULT_ABRUPT_VARS
is used as self.abruptvars
.
默认实现检查构造函数中是否提供了abruptvars
kwargs。 如果这样做,它将用作self.abruptvars
。 如果不是,则DEFAULT_ABRUPT_VARS
用作self.abruptvars
。
format_template()
format_template()
This function used imported function from alexber.utils._ymlparsers_extra
module. This module adopts its behavior dependent on availability of Python packages. This module optionally depends on ymlparseser module.
该函数使用了alexber.utils._ymlparsers_extra
模块中的导入函数。 该模块的行为取决于Python软件包的可用性。 该模块可选地取决于ymlparseser模块。
Template is expected to be compatible with Jinja2 one.
模板有望与Jinja2兼容。
Current implementation make delimiters compatible with str.format() and use it.
当前的实现使分隔符与str.format()兼容并使用它。
Note: API of this method is unstable and can change without prior notice.
注意:此方法的API不稳定,如有更改,恕不另行通知。
Note: This function will work if you have only standard Python package. You just can’t change delimiters values.
注意:如果您只有标准的Python包,则此功能将起作用。 您只是不能更改定界符值。
get_subject()
. You may override this method.get_subject()
。 您可以重写此方法。
If your subject doesn’t contains place holders, for example, Aggregates log from the Demo application
, there is no need to override this method. See also description of EmailStatus context manager above.
如果您的主题不包含占位符,例如Aggregates log from the Demo application
,则无需覆盖此方法。 另请参见上面的EmailStatus上下文管理器的描述。
If you want to change delimiters used to indicate variable declaration inside template, you have following options:
如果要更改用于指示模板内部变量声明的定界符,则可以使用以下选项:
You can override this method and pass
Jinja2 Environment
object toformat_template()
method. Note, you should ensure thatJinja2
itself and it’s dependencies are installed.您可以重写此方法,并将
Jinja2 Environment
对象传递给format_template()
方法。 注意,您应该确保已安装Jinja2
本身及其依赖项。- If your application is mutli-threaded, this object should be non-shareable (preferable, locally defined). If this object is shared, see another options below. 如果您的应用程序是多线程的,则此对象应该是不可共享的(最好是本地定义的)。 如果该对象是共享的,请参见下面的其他选项。
You can override this method and pass
Jinja2 Environment
object withthreading.RLock
(or any otherlock
) object in order to ensure atomic read of all delimeters.您可以重写此方法,并通过
threading.RLock
(或任何其他lock
)对象传递Jinja2 Environment
对象,以确保原子读取所有分度数。Call
alexber.utils.ymplparser.initConfig()
method to initializeHiYaPyCo.jinja2ctx
(together willHiYaPyCo.jinja2Lock)
. It will be consulted for delimeters informat_template()
method.调用
alexber.utils.ymplparser.initConfig()
方法来初始化HiYaPyCo.jinja2ctx
(一起将HiYaPyCo.jinja2Lock)
。 可以在format_template()
方法中查阅有关分隔符的信息。Please, note:
请注意:
* This object will be used by also by another modules (
init_app_conf
for example), so this change may effect also another parts of your applications if you use when.*此对象也将由其他模块(例如
init_app_conf
)使用,因此,如果使用when,则此更改也可能影响应用程序的其他部分。* You’re changing
*您正在改变
global variable, please make sure, you own code is aware of this change.
全局变量,请确保您自己的代码知道此更改。
* You should ensure that
*您应确保
dependencies that are required by ymplparser module are installed.
安装了ymplparser模块所需的依赖项。
See
看到
ymplparser module description for mode details.
ymplparser模块描述以获取模式详细信息。
- You can override this method with your custom logic. 您可以使用自定义逻辑覆盖此方法。
Finally, alexber.utils.emails.initConfig()
function resets some defaults.
最后, alexber.utils.emails.initConfig()
函数将重置一些默认值。
initConig() function can be optionally called prior any call to another function in this module.It is indented to be called in the MainThread
. This function can be call with empty params. This function is idempotent.
initConig()函数可以在对该模块中的另一个函数的任何调用之前被调用,它缩进在MainThread
被调用。 可以使用空参数调用此函数。 该函数是幂等的。
By default, SMTP
class from smtplib
is used to send actual e-mail. You can change it to SMTP_SSL
, LMTP
, or another class by specifying default_smtp_cls_name
.
默认情况下, smtplib
SMTP
类用于发送实际的电子邮件。 您可以通过指定default_smtp_cls_name
将其更改为SMTP_SSL
, LMTP
或其他类。
SMTP
and some other classes (but not all) has default_port
class-level field. If you use class that doesn’t have such field you have 2 options:
SMTP
和其他一些类(但不是全部)具有default_port
类级别的字段。 如果使用没有此类字段的类,则有两个选项:
Specify port in
mailhost
param toSMTPHandler
.在
mailhost
参数中指定SMTPHandler
端口。Explicitly use port in
mailhost
param to SMTPHandler as list ofmailhost
andport
.将
mailhost
参数中的port显式使用到SMTPHandler作为mailhost
和port
列表。
In any case, the order of the determination of the port is as following:
无论如何,确定端口的顺序如下:
Port in
mailhost
param toSMTPHandler
.mailhost
参数中的端口连接到SMTPHandler
。default_smtp_cls_name
if exists.default_smtp_cls_name
如果存在)。default_smtp_port
.default_smtp_port
。
Parameters are :
参数是:
default_smpt_cls_name
can be class or str. Optional. By default,SMTP
class fromsmtplib
is used to send actual e-mail. You can change it toSMTP_SSL
,LMTP
, or another class.default_smpt_cls_name
可以是class或str。 可选的。 默认情况下,smtplib
SMTP
类用于发送实际的电子邮件。 您可以将其更改为SMTP_SSL
,LMTP
或其他类。default_smtp_port
cab be int or str. . Optional. By default,smtplib.SMTP.default_port
is used. See notes above.default_smtp_port
cab为int或str。 。 可选的。 默认情况下,使用smtplib.SMTP.default_port
。 请参阅上面的注释。
也可以看看: (See also:)
fixabscwd()
function inmains
module or Making relative path to file to work.fixabscwd()
mains
功能 模块或使文件的相对路径起作用。parser module or Description of one the oldest AlexBerUtils project
ymlparsers module or Description of low-level API module for another modules
init_app_conf module, or My major init_app_con module
deploys module, or My deploys module
emails module,or My emails module
processinvokes module, or My processinvokes module
翻译自: https://medium.com/analytics-vidhya/my-emails-module-3ad36a4861c5
邮件系统 技术模块