djangomail


Namedjangomail JSON
Version 0.8 PyPI version JSON
download
home_pagehttps://github.com/somenzz/djangomail
SummaryA stand-alone mail module from django
upload_time2023-12-21 00:38:10
maintainer
docs_urlNone
authorsomenzz
requires_python
licenseMIT
keywords python send email
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI
coveralls test coverage No coveralls.
            
# djangomail

[![Build Status](https://travis-ci.com/somenzz/djangomail.svg?branch=master)](https://travis-ci.com/somenzz/djangomail)

将 mail 模块从 Django 5.0 中独立出来,做为 Python 发邮件的独立的库,就是 djangomail,使用起来比 smtplib 要方便很多。


## 安装

```shell
pip install djangomail
```


### 配置

发邮件要用户名密码和邮件服务器,对吧,直接写在配置文件里。在我们的程序的目录中,新建 settings.py 

写入以下信息:

```python
EMAIL_USE_LOCALTIME = True
EMAIL_USE_SSL = True
EMAIL_HOST = 'smtp.163.com' #可以换其他邮箱,注意修改确认端口
EMAIL_PORT = 465
EMAIL_HOST_USER = 'your-username'
EMAIL_HOST_PASSWORD = '********'
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
```

### 发送普通文本邮件

只需要导入 send_mail,send_mass_mail,设置下环境变量 `SETTINGS_MODULE`, 这是 Django 读取自定义配置文件的内容所需要的。

示例代码如下:

```python
from djangomail import send_mail,send_mass_mail
import settings

receivers = ['somenzz@163.com']

send_mail(
    subject="如何使用 django mail",
    message="djangomail 发送邮件从未如此简单,来自 「Python七号」",
    from_email=settings.DEFAULT_FROM_EMAIL,
    recipient_list=receivers
)
```

查看下邮箱:

![](https://tva1.sinaimg.cn/large/008i3skNgy1grd95qcxldj30sc0dsglv.jpg)


还可以一次发送不同的邮件给不同的人:

```python
datatuple = (
    ('Subject', 'Message.', 'from@example.com', ['john@example.com']),
    ('Subject', 'Message.', 'from@example.com', ['jane@example.com']),
)
send_mass_mail(datatuple)
```


### 发送带附件的邮件

发送附件需要使用 EmailMessage 类,其实常用的 send_mail,send_mass_mail 函数只对 EmailMessage 少数成员函数的封装。也就是说发送附件,我们需要创建 EmailMessage 对象。

示例代码如下:

```python
from djangomail import EmailMessage

import settings
import os
os.environ.setdefault("SETTINGS_MODULE", "settings") #此行代码也可以不写,默认的指向就是 settings.py

receivers = ['somenzz@163.com']

email = EmailMessage(
    subject='如何使用 djangomail 发送附件',
    body='这里有附件',
    from_email=settings.DEFAULT_FROM_EMAIL,
    to = receivers,
    reply_to=['897665600@qq.com']
)
email.attach_file("/Users/aaron/Documents/python-seven.jpg", mimetype="image/jpeg")
email.attach_file("./settings.py")
email.send()

```

检查下邮箱:

![](https://tva1.sinaimg.cn/large/008i3skNgy1grda7uakxij30vw0i874m.jpg)


### 发送多彩的 html 邮件

html 可以显示丰富多彩的内容,这里以发送一个含图片的 html 为例。

需要用到标准库里的 email 模块,添加图片信息,示例代码如下:

```python
from djangomail import EmailMultiAlternatives
from email.mime.image import MIMEImage
import settings
import os
os.environ.setdefault("SETTINGS_MODULE", "settings")


subject = 'djangomail 发送带图片的 html 邮件'

body_html = '''
<html>
    <body>
    <p>「Python七号」每周分享一个小技巧 </p>
        <img src="cid:qrcode.jpg" />
    </body>
</html>
'''


msg = EmailMultiAlternatives(
    subject,
    body_html,
    from_email=settings.DEFAULT_FROM_EMAIL,
    to=['somenzz@163.com']
)

msg.mixed_subtype = 'related'
msg.attach_alternative(body_html, "text/html")
img_dir = 'images/'
image = 'qrcode.jpg'
file_path = os.path.join(img_dir, image)
with open(file_path, 'rb') as f:
    img = MIMEImage(f.read())
    img.add_header('Content-ID', '<{name}>'.format(name=image))
    img.add_header('Content-Disposition', 'inline', filename=image)
msg.attach(img)

msg.send()
```

检查下邮箱,发现图片直接显示在了邮件内容中:

![](https://tva1.sinaimg.cn/large/008i3skNgy1grdb1hawpyj31d60s8dhw.jpg)


### 扩展

其实不止发送邮件,通过实现自己的 Backend,就可以将消息发送到任何平台。

django 自己的 global_settings 其实已经有以下配置:

```python
EMAIL_BACKEND = 'djangomail.backends.smtp.EmailBackend'
```

只要我们按照 EmailBackend 的格式编写自己的 Backend 就可以实现自定义的消息发送,比如说发送到微信。

然后修改 settings.py 文件,将 EMAIL_BACKEND 配置为自己的 Backend 即可。 

EmailBackend 继承自类 BaseEmailBackend,假如我们编写自己的 MyBackend,只需要继承 BaseEmailBackend 实现它的 send_messages 方法即可:

```python
def send_messages(self, email_messages):
    """
    Send one or more EmailMessage objects and return the number of email
    messages sent.
    """
    raise NotImplementedError(
        "subclasses of BaseEmailBackend must override send_messages() method"
    )
```

有个 [server酱](https://mp.weixin.qq.com/s/ibBaPbMg202XMEaG-zifVA) 可以发送到微信,你可以自己扩展下,我这里就不展开了。


### 报错自动发送邮件

当某个函数报错,也就是抛出异常时,如果发送异常相关的堆栈信息邮件给运维人员,则可以大大提升处理效率。

当然了,可以指定某些异常,只有抛出这类异常时才发邮件,也可以将不同的异常发给不同的人。

这里我已经做好了一个装饰器:somedecorators

##### 安装

```sh
pip install somedecorators
```

##### 使用

```python
from somedecorators import email_on_exception
import os
os.environ.setdefault("SETTINGS_MODULE", "settings")

@email_on_exception(['somenzz@163.com'])
def myfunc():
    1/0

myfunc()
```

检查一下邮箱:

![](https://tva1.sinaimg.cn/large/008i3skNgy1grdbaqr7ooj31e60n43zx.jpg)

##### 监控指定的异常

```python

from somedecorators import email_on_exception
import os
os.environ.setdefault("SETTINGS_MODULE", "settings")

class Exception1(Exception):
    pass

class Exception2(Exception):
    pass

class Exception3(Exception):
    pass

@email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2)
def myfunc(args):
    if args == 1:
        raise Exception1
    elif args == 2:
        raise Exception2
    else:
        raise Exception3

myfunc(2)

```
上述代码只有在 raise Exception2 时才会发送邮件:

![](https://tva1.sinaimg.cn/large/008i3skNgy1grdbh8d2foj31de0l2myd.jpg)

##### 不同的异常发给不同的人


```python
@email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2)
@email_on_exception(['others@163.com'],traced_exceptions = (Exception1, Exception3))
def myfunc(args):
    if args == 1:
        raise Exception1
    elif args == 2:
        raise Exception2
    else:
        raise Exception3
```

是不是非常方便?

##### 其他装饰器

**timeit**

耗时统计装饰器,单位是秒,保留 4 位小数

使用方法:

```python
from somedecorators import timeit
@timeit()
def test_timeit():
    time.sleep(1)

#test_timeit cost 1.0026 seconds

@timeit(logger = your_logger)
def test_timeit():
    time.sleep(1)
```

**retry**

重试装饰器。

当被装饰的函数调用抛出指定的异常时,函数会被重新调用。

直到达到指定的最大调用次数才重新抛出指定的异常,可以指定时间间隔,默认 5 秒后重试。

traced_exceptions 为监控的异常,可以为 None(默认)、异常类、或者一个异常类的列表或元组 tuple。

traced_exceptions 如果为 None,则监控所有的异常;如果指定了异常类,则若函数调用抛出指定的异常时,重新调用函数,直至成功返回结果。

未出现监控的异常时,如果指定定了 reraised_exception 则抛出 reraised_exception,否则抛出原来的异常。

```python
from somedecorators import retry 

@retry(
    times=2,
    wait_seconds=1,
    traced_exceptions=myException,
    reraised_exception=CustomException,
)
def test_retry():
    # time.sleep(1)
    raise myException


test_retry()
```

### 其他实用三方库

- [dbinterface](https://github.com/somenzz/dbinterface): 数据库统一读、写、导出文件接口,适用于数据仓库等多数据库系统应用。支持 db2、mysql,postgres。

- [transferfile](https://github.com/somenzz/transferfile): 文件上传、下载接口,适用于文件分发系统。支持 ftp、sftp、scp、rsync。


### 联系我

公众号「Python七号」

微信号「somenzz-enjoy」

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/somenzz/djangomail",
    "name": "djangomail",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "python send email",
    "author": "somenzz",
    "author_email": "somenzz@163.com",
    "download_url": "https://files.pythonhosted.org/packages/27/34/84452127cf32b20175e44d2f1599b187f7270089142399d1087ca90dc30b/djangomail-0.8.tar.gz",
    "platform": null,
    "description": "\n# djangomail\n\n[![Build Status](https://travis-ci.com/somenzz/djangomail.svg?branch=master)](https://travis-ci.com/somenzz/djangomail)\n\n\u5c06 mail \u6a21\u5757\u4ece Django 5.0 \u4e2d\u72ec\u7acb\u51fa\u6765\uff0c\u505a\u4e3a Python \u53d1\u90ae\u4ef6\u7684\u72ec\u7acb\u7684\u5e93\uff0c\u5c31\u662f djangomail\uff0c\u4f7f\u7528\u8d77\u6765\u6bd4 smtplib \u8981\u65b9\u4fbf\u5f88\u591a\u3002\n\n\n## \u5b89\u88c5\n\n```shell\npip install djangomail\n```\n\n\n### \u914d\u7f6e\n\n\u53d1\u90ae\u4ef6\u8981\u7528\u6237\u540d\u5bc6\u7801\u548c\u90ae\u4ef6\u670d\u52a1\u5668\uff0c\u5bf9\u5427\uff0c\u76f4\u63a5\u5199\u5728\u914d\u7f6e\u6587\u4ef6\u91cc\u3002\u5728\u6211\u4eec\u7684\u7a0b\u5e8f\u7684\u76ee\u5f55\u4e2d\uff0c\u65b0\u5efa settings.py \n\n\u5199\u5165\u4ee5\u4e0b\u4fe1\u606f\uff1a\n\n```python\nEMAIL_USE_LOCALTIME = True\nEMAIL_USE_SSL = True\nEMAIL_HOST = 'smtp.163.com' #\u53ef\u4ee5\u6362\u5176\u4ed6\u90ae\u7bb1\uff0c\u6ce8\u610f\u4fee\u6539\u786e\u8ba4\u7aef\u53e3\nEMAIL_PORT = 465\nEMAIL_HOST_USER = 'your-username'\nEMAIL_HOST_PASSWORD = '********'\nDEFAULT_FROM_EMAIL = EMAIL_HOST_USER\n```\n\n### \u53d1\u9001\u666e\u901a\u6587\u672c\u90ae\u4ef6\n\n\u53ea\u9700\u8981\u5bfc\u5165 send_mail,send_mass_mail\uff0c\u8bbe\u7f6e\u4e0b\u73af\u5883\u53d8\u91cf `SETTINGS_MODULE`\uff0c \u8fd9\u662f Django \u8bfb\u53d6\u81ea\u5b9a\u4e49\u914d\u7f6e\u6587\u4ef6\u7684\u5185\u5bb9\u6240\u9700\u8981\u7684\u3002\n\n\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b\uff1a\n\n```python\nfrom djangomail import send_mail,send_mass_mail\nimport settings\n\nreceivers = ['somenzz@163.com']\n\nsend_mail(\n    subject=\"\u5982\u4f55\u4f7f\u7528 django mail\",\n    message=\"djangomail \u53d1\u9001\u90ae\u4ef6\u4ece\u672a\u5982\u6b64\u7b80\u5355\uff0c\u6765\u81ea \u300cPython\u4e03\u53f7\u300d\",\n    from_email=settings.DEFAULT_FROM_EMAIL,\n    recipient_list=receivers\n)\n```\n\n\u67e5\u770b\u4e0b\u90ae\u7bb1\uff1a\n\n![](https://tva1.sinaimg.cn/large/008i3skNgy1grd95qcxldj30sc0dsglv.jpg)\n\n\n\u8fd8\u53ef\u4ee5\u4e00\u6b21\u53d1\u9001\u4e0d\u540c\u7684\u90ae\u4ef6\u7ed9\u4e0d\u540c\u7684\u4eba\uff1a\n\n```python\ndatatuple = (\n    ('Subject', 'Message.', 'from@example.com', ['john@example.com']),\n    ('Subject', 'Message.', 'from@example.com', ['jane@example.com']),\n)\nsend_mass_mail(datatuple)\n```\n\n\n### \u53d1\u9001\u5e26\u9644\u4ef6\u7684\u90ae\u4ef6\n\n\u53d1\u9001\u9644\u4ef6\u9700\u8981\u4f7f\u7528 EmailMessage \u7c7b\uff0c\u5176\u5b9e\u5e38\u7528\u7684 send_mail,send_mass_mail \u51fd\u6570\u53ea\u5bf9 EmailMessage \u5c11\u6570\u6210\u5458\u51fd\u6570\u7684\u5c01\u88c5\u3002\u4e5f\u5c31\u662f\u8bf4\u53d1\u9001\u9644\u4ef6\uff0c\u6211\u4eec\u9700\u8981\u521b\u5efa EmailMessage \u5bf9\u8c61\u3002\n\n\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b\uff1a\n\n```python\nfrom djangomail import EmailMessage\n\nimport settings\nimport os\nos.environ.setdefault(\"SETTINGS_MODULE\", \"settings\") #\u6b64\u884c\u4ee3\u7801\u4e5f\u53ef\u4ee5\u4e0d\u5199\uff0c\u9ed8\u8ba4\u7684\u6307\u5411\u5c31\u662f settings.py\n\nreceivers = ['somenzz@163.com']\n\nemail = EmailMessage(\n    subject='\u5982\u4f55\u4f7f\u7528 djangomail \u53d1\u9001\u9644\u4ef6',\n    body='\u8fd9\u91cc\u6709\u9644\u4ef6',\n    from_email=settings.DEFAULT_FROM_EMAIL,\n    to = receivers,\n    reply_to=['897665600@qq.com']\n)\nemail.attach_file(\"/Users/aaron/Documents/python-seven.jpg\", mimetype=\"image/jpeg\")\nemail.attach_file(\"./settings.py\")\nemail.send()\n\n```\n\n\u68c0\u67e5\u4e0b\u90ae\u7bb1\uff1a\n\n![](https://tva1.sinaimg.cn/large/008i3skNgy1grda7uakxij30vw0i874m.jpg)\n\n\n### \u53d1\u9001\u591a\u5f69\u7684 html \u90ae\u4ef6\n\nhtml \u53ef\u4ee5\u663e\u793a\u4e30\u5bcc\u591a\u5f69\u7684\u5185\u5bb9\uff0c\u8fd9\u91cc\u4ee5\u53d1\u9001\u4e00\u4e2a\u542b\u56fe\u7247\u7684 html \u4e3a\u4f8b\u3002\n\n\u9700\u8981\u7528\u5230\u6807\u51c6\u5e93\u91cc\u7684 email \u6a21\u5757\uff0c\u6dfb\u52a0\u56fe\u7247\u4fe1\u606f\uff0c\u793a\u4f8b\u4ee3\u7801\u5982\u4e0b\uff1a\n\n```python\nfrom djangomail import EmailMultiAlternatives\nfrom email.mime.image import MIMEImage\nimport settings\nimport os\nos.environ.setdefault(\"SETTINGS_MODULE\", \"settings\")\n\n\nsubject = 'djangomail \u53d1\u9001\u5e26\u56fe\u7247\u7684 html \u90ae\u4ef6'\n\nbody_html = '''\n<html>\n    <body>\n    <p>\u300cPython\u4e03\u53f7\u300d\u6bcf\u5468\u5206\u4eab\u4e00\u4e2a\u5c0f\u6280\u5de7 </p>\n        <img src=\"cid:qrcode.jpg\" />\n    </body>\n</html>\n'''\n\n\nmsg = EmailMultiAlternatives(\n    subject,\n    body_html,\n    from_email=settings.DEFAULT_FROM_EMAIL,\n    to=['somenzz@163.com']\n)\n\nmsg.mixed_subtype = 'related'\nmsg.attach_alternative(body_html, \"text/html\")\nimg_dir = 'images/'\nimage = 'qrcode.jpg'\nfile_path = os.path.join(img_dir, image)\nwith open(file_path, 'rb') as f:\n    img = MIMEImage(f.read())\n    img.add_header('Content-ID', '<{name}>'.format(name=image))\n    img.add_header('Content-Disposition', 'inline', filename=image)\nmsg.attach(img)\n\nmsg.send()\n```\n\n\u68c0\u67e5\u4e0b\u90ae\u7bb1\uff0c\u53d1\u73b0\u56fe\u7247\u76f4\u63a5\u663e\u793a\u5728\u4e86\u90ae\u4ef6\u5185\u5bb9\u4e2d\uff1a\n\n![](https://tva1.sinaimg.cn/large/008i3skNgy1grdb1hawpyj31d60s8dhw.jpg)\n\n\n### \u6269\u5c55\n\n\u5176\u5b9e\u4e0d\u6b62\u53d1\u9001\u90ae\u4ef6\uff0c\u901a\u8fc7\u5b9e\u73b0\u81ea\u5df1\u7684 Backend\uff0c\u5c31\u53ef\u4ee5\u5c06\u6d88\u606f\u53d1\u9001\u5230\u4efb\u4f55\u5e73\u53f0\u3002\n\ndjango \u81ea\u5df1\u7684 global_settings \u5176\u5b9e\u5df2\u7ecf\u6709\u4ee5\u4e0b\u914d\u7f6e\uff1a\n\n```python\nEMAIL_BACKEND = 'djangomail.backends.smtp.EmailBackend'\n```\n\n\u53ea\u8981\u6211\u4eec\u6309\u7167 EmailBackend \u7684\u683c\u5f0f\u7f16\u5199\u81ea\u5df1\u7684 Backend \u5c31\u53ef\u4ee5\u5b9e\u73b0\u81ea\u5b9a\u4e49\u7684\u6d88\u606f\u53d1\u9001\uff0c\u6bd4\u5982\u8bf4\u53d1\u9001\u5230\u5fae\u4fe1\u3002\n\n\u7136\u540e\u4fee\u6539 settings.py \u6587\u4ef6\uff0c\u5c06 EMAIL_BACKEND \u914d\u7f6e\u4e3a\u81ea\u5df1\u7684 Backend \u5373\u53ef\u3002 \n\nEmailBackend \u7ee7\u627f\u81ea\u7c7b BaseEmailBackend\uff0c\u5047\u5982\u6211\u4eec\u7f16\u5199\u81ea\u5df1\u7684 MyBackend\uff0c\u53ea\u9700\u8981\u7ee7\u627f BaseEmailBackend \u5b9e\u73b0\u5b83\u7684 send_messages \u65b9\u6cd5\u5373\u53ef\uff1a\n\n```python\ndef send_messages(self, email_messages):\n    \"\"\"\n    Send one or more EmailMessage objects and return the number of email\n    messages sent.\n    \"\"\"\n    raise NotImplementedError(\n        \"subclasses of BaseEmailBackend must override send_messages() method\"\n    )\n```\n\n\u6709\u4e2a [server\u9171](https://mp.weixin.qq.com/s/ibBaPbMg202XMEaG-zifVA) \u53ef\u4ee5\u53d1\u9001\u5230\u5fae\u4fe1\uff0c\u4f60\u53ef\u4ee5\u81ea\u5df1\u6269\u5c55\u4e0b\uff0c\u6211\u8fd9\u91cc\u5c31\u4e0d\u5c55\u5f00\u4e86\u3002\n\n\n### \u62a5\u9519\u81ea\u52a8\u53d1\u9001\u90ae\u4ef6\n\n\u5f53\u67d0\u4e2a\u51fd\u6570\u62a5\u9519\uff0c\u4e5f\u5c31\u662f\u629b\u51fa\u5f02\u5e38\u65f6\uff0c\u5982\u679c\u53d1\u9001\u5f02\u5e38\u76f8\u5173\u7684\u5806\u6808\u4fe1\u606f\u90ae\u4ef6\u7ed9\u8fd0\u7ef4\u4eba\u5458\uff0c\u5219\u53ef\u4ee5\u5927\u5927\u63d0\u5347\u5904\u7406\u6548\u7387\u3002\n\n\u5f53\u7136\u4e86\uff0c\u53ef\u4ee5\u6307\u5b9a\u67d0\u4e9b\u5f02\u5e38\uff0c\u53ea\u6709\u629b\u51fa\u8fd9\u7c7b\u5f02\u5e38\u65f6\u624d\u53d1\u90ae\u4ef6\uff0c\u4e5f\u53ef\u4ee5\u5c06\u4e0d\u540c\u7684\u5f02\u5e38\u53d1\u7ed9\u4e0d\u540c\u7684\u4eba\u3002\n\n\u8fd9\u91cc\u6211\u5df2\u7ecf\u505a\u597d\u4e86\u4e00\u4e2a\u88c5\u9970\u5668\uff1asomedecorators\n\n##### \u5b89\u88c5\n\n```sh\npip install somedecorators\n```\n\n##### \u4f7f\u7528\n\n```python\nfrom somedecorators import email_on_exception\nimport os\nos.environ.setdefault(\"SETTINGS_MODULE\", \"settings\")\n\n@email_on_exception(['somenzz@163.com'])\ndef myfunc():\n    1/0\n\nmyfunc()\n```\n\n\u68c0\u67e5\u4e00\u4e0b\u90ae\u7bb1\uff1a\n\n![](https://tva1.sinaimg.cn/large/008i3skNgy1grdbaqr7ooj31e60n43zx.jpg)\n\n##### \u76d1\u63a7\u6307\u5b9a\u7684\u5f02\u5e38\n\n```python\n\nfrom somedecorators import email_on_exception\nimport os\nos.environ.setdefault(\"SETTINGS_MODULE\", \"settings\")\n\nclass Exception1(Exception):\n    pass\n\nclass Exception2(Exception):\n    pass\n\nclass Exception3(Exception):\n    pass\n\n@email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2)\ndef myfunc(args):\n    if args == 1:\n        raise Exception1\n    elif args == 2:\n        raise Exception2\n    else:\n        raise Exception3\n\nmyfunc(2)\n\n```\n\u4e0a\u8ff0\u4ee3\u7801\u53ea\u6709\u5728 raise Exception2 \u65f6\u624d\u4f1a\u53d1\u9001\u90ae\u4ef6\uff1a\n\n![](https://tva1.sinaimg.cn/large/008i3skNgy1grdbh8d2foj31de0l2myd.jpg)\n\n##### \u4e0d\u540c\u7684\u5f02\u5e38\u53d1\u7ed9\u4e0d\u540c\u7684\u4eba\n\n\n```python\n@email_on_exception(['somenzz@163.com'],traced_exceptions = Exception2)\n@email_on_exception(['others@163.com'],traced_exceptions = (Exception1, Exception3))\ndef myfunc(args):\n    if args == 1:\n        raise Exception1\n    elif args == 2:\n        raise Exception2\n    else:\n        raise Exception3\n```\n\n\u662f\u4e0d\u662f\u975e\u5e38\u65b9\u4fbf\uff1f\n\n##### \u5176\u4ed6\u88c5\u9970\u5668\n\n**timeit**\n\n\u8017\u65f6\u7edf\u8ba1\u88c5\u9970\u5668\uff0c\u5355\u4f4d\u662f\u79d2\uff0c\u4fdd\u7559 4 \u4f4d\u5c0f\u6570\n\n\u4f7f\u7528\u65b9\u6cd5\uff1a\n\n```python\nfrom somedecorators import timeit\n@timeit()\ndef test_timeit():\n    time.sleep(1)\n\n#test_timeit cost 1.0026 seconds\n\n@timeit(logger = your_logger)\ndef test_timeit():\n    time.sleep(1)\n```\n\n**retry**\n\n\u91cd\u8bd5\u88c5\u9970\u5668\u3002\n\n\u5f53\u88ab\u88c5\u9970\u7684\u51fd\u6570\u8c03\u7528\u629b\u51fa\u6307\u5b9a\u7684\u5f02\u5e38\u65f6\uff0c\u51fd\u6570\u4f1a\u88ab\u91cd\u65b0\u8c03\u7528\u3002\n\n\u76f4\u5230\u8fbe\u5230\u6307\u5b9a\u7684\u6700\u5927\u8c03\u7528\u6b21\u6570\u624d\u91cd\u65b0\u629b\u51fa\u6307\u5b9a\u7684\u5f02\u5e38\uff0c\u53ef\u4ee5\u6307\u5b9a\u65f6\u95f4\u95f4\u9694\uff0c\u9ed8\u8ba4 5 \u79d2\u540e\u91cd\u8bd5\u3002\n\ntraced_exceptions \u4e3a\u76d1\u63a7\u7684\u5f02\u5e38\uff0c\u53ef\u4ee5\u4e3a None\uff08\u9ed8\u8ba4\uff09\u3001\u5f02\u5e38\u7c7b\u3001\u6216\u8005\u4e00\u4e2a\u5f02\u5e38\u7c7b\u7684\u5217\u8868\u6216\u5143\u7ec4 tuple\u3002\n\ntraced_exceptions \u5982\u679c\u4e3a None\uff0c\u5219\u76d1\u63a7\u6240\u6709\u7684\u5f02\u5e38\uff1b\u5982\u679c\u6307\u5b9a\u4e86\u5f02\u5e38\u7c7b\uff0c\u5219\u82e5\u51fd\u6570\u8c03\u7528\u629b\u51fa\u6307\u5b9a\u7684\u5f02\u5e38\u65f6\uff0c\u91cd\u65b0\u8c03\u7528\u51fd\u6570\uff0c\u76f4\u81f3\u6210\u529f\u8fd4\u56de\u7ed3\u679c\u3002\n\n\u672a\u51fa\u73b0\u76d1\u63a7\u7684\u5f02\u5e38\u65f6\uff0c\u5982\u679c\u6307\u5b9a\u5b9a\u4e86 reraised_exception \u5219\u629b\u51fa reraised_exception\uff0c\u5426\u5219\u629b\u51fa\u539f\u6765\u7684\u5f02\u5e38\u3002\n\n```python\nfrom somedecorators import retry \n\n@retry(\n    times=2,\n    wait_seconds=1,\n    traced_exceptions=myException,\n    reraised_exception=CustomException,\n)\ndef test_retry():\n    # time.sleep(1)\n    raise myException\n\n\ntest_retry()\n```\n\n### \u5176\u4ed6\u5b9e\u7528\u4e09\u65b9\u5e93\n\n- [dbinterface](https://github.com/somenzz/dbinterface): \u6570\u636e\u5e93\u7edf\u4e00\u8bfb\u3001\u5199\u3001\u5bfc\u51fa\u6587\u4ef6\u63a5\u53e3\uff0c\u9002\u7528\u4e8e\u6570\u636e\u4ed3\u5e93\u7b49\u591a\u6570\u636e\u5e93\u7cfb\u7edf\u5e94\u7528\u3002\u652f\u6301 db2\u3001mysql\uff0cpostgres\u3002\n\n- [transferfile](https://github.com/somenzz/transferfile): \u6587\u4ef6\u4e0a\u4f20\u3001\u4e0b\u8f7d\u63a5\u53e3\uff0c\u9002\u7528\u4e8e\u6587\u4ef6\u5206\u53d1\u7cfb\u7edf\u3002\u652f\u6301 ftp\u3001sftp\u3001scp\u3001rsync\u3002\n\n\n### \u8054\u7cfb\u6211\n\n\u516c\u4f17\u53f7\u300cPython\u4e03\u53f7\u300d\n\n\u5fae\u4fe1\u53f7\u300csomenzz-enjoy\u300d\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A stand-alone mail module from django",
    "version": "0.8",
    "project_urls": {
        "Homepage": "https://github.com/somenzz/djangomail"
    },
    "split_keywords": [
        "python",
        "send",
        "email"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c918019259cf49167c3a52b29ee5cbf51f58634f63148771bc1c494c5b3ca27f",
                "md5": "78e3ca1ef9005082809022644ff2af0c",
                "sha256": "52f3e3747ae77b9d6fdc7c4b6fe16997dd0c813d6fa89769e288b6606fe313bb"
            },
            "downloads": -1,
            "filename": "djangomail-0.8-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "78e3ca1ef9005082809022644ff2af0c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 41136,
            "upload_time": "2023-12-21T00:38:08",
            "upload_time_iso_8601": "2023-12-21T00:38:08.451157Z",
            "url": "https://files.pythonhosted.org/packages/c9/18/019259cf49167c3a52b29ee5cbf51f58634f63148771bc1c494c5b3ca27f/djangomail-0.8-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "273484452127cf32b20175e44d2f1599b187f7270089142399d1087ca90dc30b",
                "md5": "636d3db126f5b812f273791422b293cd",
                "sha256": "050ed40fccf631b67c3494547b1bed7d21db4eaf6a0ca988ce8b9501b199fedb"
            },
            "downloads": -1,
            "filename": "djangomail-0.8.tar.gz",
            "has_sig": false,
            "md5_digest": "636d3db126f5b812f273791422b293cd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 40543,
            "upload_time": "2023-12-21T00:38:10",
            "upload_time_iso_8601": "2023-12-21T00:38:10.635461Z",
            "url": "https://files.pythonhosted.org/packages/27/34/84452127cf32b20175e44d2f1599b187f7270089142399d1087ca90dc30b/djangomail-0.8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-21 00:38:10",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "somenzz",
    "github_project": "djangomail",
    "travis_ci": true,
    "coveralls": false,
    "github_actions": false,
    "tox": true,
    "lcname": "djangomail"
}
        
Elapsed time: 0.19966s