Python高级功能

标签: Python 分类: Python 创建时间:2020-06-15 12:51:34 更新时间:2025-01-17 10:39:22

1.发送邮件

发送邮件其实也是简单的,菜鸟教程上,跟着做就好了,没有任何的压力。

2.导入当前目录下的文件

在windos下,如果想要导入当前目录下的文件,需要先使用sys.path.append(‘.’)将当前目录加入到环境变量中,然后再进行导入包的操作,linux就不需要。但是导入上级目录模块,就需要处理了。

1
2
3
4
5
6
7
8
#!/usr/bin/python3
# -*- coding: UTF-8 -*-

import sys
## 导入当前目录包
sys.path.append('.')
## 导入邮件发送
import qqmail

注意:如果一个文件作为一个单独的py文件执行,使用sys.path.append(‘.’)导入当前包是没有问题的,但是如果是作为一个子包引入,就会存在问题,还是找不到相应的包。解决方法就是使用from的引入方法代替import方法,比如下面的代码,从当前目录下的PYSQL.py文件中导入类MSSQL

1
from .PYSQL import MSSQL

有如下的解释:

对于不在sys.path中,一定要避免用import导入 自定义包(package)的子模块(module),而要用from…import… 的绝对导入 或相对导入,且包(package)的相对导入只能用from形式。

【解决方案】

1
2
3
4
5
6
7
8
import os
# 导入当前目录模块
sys.path.append("..")
from . import classes

# 导入运行目录模块
sys.path.append(os.path.dirname(sys.path[0]))
from . import classes
参考文章:
【1】.python import 如何引入当前目录的.py文件?
【2】.Python 3.x可能是史上最详解的【导入(import)】
【3】.python模块以及导入出现ImportError: No module named ‘xxx’问题
【4】.python基础-同级包模块导入、__init__、syspath导入存在的问题、绝对相对导入、单独包导入 (sys.path导入模块错误原因,这里有说明为什么使用sys.path无法导入当前目录下的包,这是因为在使用单独运行的py文件时,可以使用sys.path,但是如果不是单独运行的,那就会出现问题,但是这篇文章写的有点乱)
【5】.Python 3.x可能是史上最详解的【导入(import)】
【6】.python找不到上级目录的模块?详解其中的奥妙 在windows下pycharm环境中运行一个python项目时是正常的,放在Linux下使用python命令运行就出了错误。提示 ModuleNotFoundError: No module named ‘xxx’。pycharm中为什么不存在这个问题,点击菜单栏Run->Edit Configuration,有一个 Working directory 模块配置。

3.软件包

1
2
3
4
5
6
7
8
9
10
11
12
# 方式一,这里生成的txt,但是vscode里面打开乱码
pip freeze > requirements.txt

## 恢复
$ pip install -r requirements.txt

# 方式二
pip install pipreqs
# 生成当前项目的 安装包
pipreqs .
# 安装
pip install -r requirements.txt
参考文章:
【1】.python 项目自动生成requirements.txt文件 方法一:pip freeze > requirements.txt;方法二:pip install pipreqs
【2】.如何指定pip freeze > requirements.txt生成的文件的编码为UTF-8?
【3】.python freeze 和 恢复

4.linux后台运行pyhton

在linux上后台运行某一个程序,可以使用 nohup ,但是随之而来的另外一个问题,那就是如何在某一个虚拟环境中后台运行某一个程序。

或者是我想错了吗?在使用conda切换虚拟环境之后,然后后台运行,自然还是在这个虚拟环境下运行的。

1
2
3
4
5
6
7
8
## 后台运行
nohup python /data/python/server.py > python.log3 2>&1 &

## 查看进程
ps aux|grep python

## 杀死进程
kill -9 [上一步的进程号]
参考文章:
【1】.linux 下后台运行python脚本
【2】.Linux如何在后台一直运行python程序 后台运行python代码命令:nohup python3 main.py &
【3】.Linux下系统自带python和Anaconda切换

5.工程

(1) 通常的 python 项目,都是以单文件的形式执行的,后来要是做一个Ai识别的项目,就需要工程化的思想了。参考目录如下:

1
2
3
4
5
6
7
8
9
10
11
README.rst
LICENSE
setup.py
requirements.txt
sample/__init__.py
sample/core.py
sample/helpers.py
docs/conf.py
docs/index.rst
tests/test_basic.py
tests/test_advanced.py

(2) Python 项目的目录结构因项目而异,但通常会包含以下几个主要目录和文件:

  • README.md:项目文档,包括项目介绍、安装、使用方法等。
  • LICENSE:项目许可证,规定了项目的使用条件。
  • requirements.txt:记录项目所需的依赖包及其版本号,方便其他人快速安装相应的依赖包。
  • setup.py:定义项目的安装方法,可以通过该文件将项目发布到 PyPI 上。
  • src/:存放项目源代码的主目录。
  • tests/:存放项目测试代码的目录,包括单元测试、集成测试、端到端测试等。
  • docs/:存放项目文档的目录,包括 API 文档、用户手册、设计文档等。
  • data/:存放项目中用到的数据文件等资源。
  • scripts/:存放项目相关的脚本文件,例如批处理文件、自动化部署脚本等。

(3) 当谈到 Python Web 项目时

  • app/:存放应用程序的主目录,包含了处理请求、路由、业务逻辑和数据模型等功能模块。该目录中一般会包含多个 Python 模块。
  • config/:存放配置文件的目录,例如数据库配置、日志配置等。
  • static/:存放静态资源,例如 CSS、JavaScript 和图片等文件。
  • templates/:存放 HTML 模板文件的目录,这些模板将在应用程序中动态生成。
  • tests/:存放测试代码的目录,用于测试应用程序的各种功能和接口。
  • venv/:Python 虚拟环境,用于隔离项目依赖,保证项目的稳定性和可移植性。
  • requirements.txt:记录项目所需的依赖包及其版本号,方便其他人快速安装相应的依赖包。
  • README.md:项目文档,包括项目介绍、安装、使用方法等。
参考文章:
【1】.Python 项目工程化开发指南
【2】.Python 项目工程化开发指南 这里好像一个整体的项目说明
【3】.结构化您的工程 真正的模块 ./sample/ or ./sample.py。Setup.py 如果您的模块包在您的根目录下,显然这个文件也应该在根目录下。Requirements File 一个 pip requirements file 应该放在仓库的根目录。它应该指明完整工程的所有依赖包: 测试, 编译和文档生成。任意包含 init.py 文件的目录都被认为是一个Python包。导入一个包里不同 模块的方式和普通的导入模块方式相似,特别的地方是 init.py 文件将集合 所有包范围内的定义。
【4】.Python 项目以及常见的目录结构 其目录结构与一般 Python 项目略有不同。Python Web 项目通常包括以下主要目录和文件
【5】.python项目结构的最佳实践 选择了 FastAPI 实现简单的服务器。
【6】.教程 - 用户指南 本教程将一步步向你展示如何使用 FastAPI 的绝大部分特性。各个章节的内容循序渐进,但是又围绕着单独的主题,所以你可以直接跳转到某个章节以解决你的特定需求

6.日志

使用 python 的日志框架

1
pip install loguru

配置按天分割文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from loguru import logger
logger = logger.opt(colors=True)
# 配置日志记录文件
# 设置日志文件的路径和格式
LOG_FILE = "app.log"
LOG_FORMAT = "<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{message}</level>"
logger.remove() # 移除所有默认的日志处理器
logger.add(
LOG_FILE, # 日志文件路径
format=LOG_FORMAT, # 日志格式
rotation="1 day", # 每天旋转日志文件
compression="zip", # 压缩日志文件
retention="7 day" # 保留7天的日志文件
)
logger.add(sys.stdout,level="INFO") # 输出到标准输出
参考文章:
【1】.python日志记录loguru以及如何记录到两个日志文件中
【2】.Delgan /loguru
【3】.Python 日志记录:6大日志记录库的比较 1.logging - 内置的标准日志模块。2.Loguru - 最流行的Python第三方日志框架。3.Structlog。4.Eliot。5.Logbook。6.Picologging。
【4】.loguru设置按天分割日志,保留1天内容 在上面的示例中,我们定义了 [loguru] 和 [loguru.handlers.file] 两个部分。
【5】.【拓展】Loguru:更为优雅、简洁的Python 日志管理模块
【6】.Python loguru 多个模块使用一个logger对象 这篇文章写了多文件共用了一个logger的情况,在使用loguru库之前,我们需要创建一个全局的logger对象,这样不同的模块就可以共享同一个logger对象。可以使用以下代码创建logger对象。
【7】.python loguru 日志级别与按天分割并删除历史日志实践 在 loguru 库中,使用 rotation 参数来按时间间隔分隔日志,同时使用 retention 参数来自动删除旧的日志文件。
【8】.Python 日志模块Loguru基本使用和封装使用 Loguru与logging的区别和优势:简洁性、自动化、灵活性、高效性。封装一个loguru,目录结构:一般都是放在一个utils文件夹下,提供了相关的配置文件。

7.Mino操作

参考文章:
【1】.Python Minio 工具类封装 写了一个 Minio 的工具类。
【2】.MinIO服务器搭建步骤 python 操作MinIO,这里封装之后的接口,和上面的一样:1.查询桶是否存在。2.上传文件,若文件已存在,会直接覆盖。3.获取文件数据写入指定文件。4.直接将文件下载到本地。5.删除文件。6.删除多个文件。

8.OpenCV

在进行图像识别的时候,大部分还是借助于 OpenCV 的接口。

8.1.实时帧

1
fps =cap.get(cv2.CAP_PROP_FPS)

8.2.missing picture in access unit with size

我在使用opencv进行处理的时候,使用obs进行推流的时候,不会出现问题,但是使用 无人机 推流的时候,地址都是同样的地址,但是就是无法实现拉流,然后报错:missing picture in access unit with size

【尝试解决】
(1)我尝试读取是否为空的问题

1
2
3
4
5
6
7
# 判断是否为空操作,如果为空则不进行处理
if frame.empty():
self.cnt+=1
if self.cnt == 10:
self.cnt = 0
break
continue
参考文章:
【1】.opencv拉流出现missing picture in access unit with size 4错误解决
【2】.ffmpeg转码时出现missing picture in access unit with size 14019 索性截取掉最后的2秒时间
【3】.pilot2 rtmp 直播推流问题 这里是同样的问题,机场视频没有问题,但是 DJI pilot 2 的问题。

8.3.关闭日志输出

opencv日志总是输出很多没有用的,我感觉有些烦人,于是就想着要把他关掉。很多文章都用了 loggin,但是就是无法关闭 ffmpeg 的日志输出,真是扯淡啊。

【尝试方案】
(1)尝试使用 python 设置,感觉无效

1
2
# 无效
cv2.setLogLevel(0)

(2)尝试设置环境变量,也无效

1
2
3
import os
os.environ["OPENCV_LOG_LEVEL"] = "0"
import cv2

(3)尝试使用 set 设置环境变量

1
set OPENCV_LOG_LEVEL=0

(4)设置多个变量,也还是无效

1
2
3
4
5
6
7
8
9
import os
os.environ["OPENCV_VIDEOIO_DEBUG"] = "0"
os.environ["OPENCV_FFMPEG_DEBUG"] = "0"
os.environ["OPENCV_VIDEOWRITER_DEBUG"] = "0"
os.environ["OPENCV_VIDEOCAPTURE_DEBUG"] = "0"
os.environ["OPENCV_FFMPEG_LOGLEVEL"] = "-8"
os.environ["OPENCV_FFMPEG_LOGLEVEL"]="-8"
os.environ["OPENCV_LOG_LEVEL"]="OFF"
import cv2

(5)使用 logging 进行屏蔽,也无效

1
2
3
4
5
6
7
import logging
# 创建一个Logger对象
logger = logging.getLogger(__name__)
# 获取第三方库的Logger对象
requests_logger = logging.getLogger('cv2')
# 设置第三方库的Logger级别为WARNING
requests_logger.setLevel(logging.ERROR)

(6)禁用print
我打算直接禁用全部的 print ,结果还是没用,还是输出一堆的 [NULl]

1
2
3
4
5
6
7
8
9
10
import os,sys
# Disable
def blockPrint():
sys.stdout = open(os.devnull, 'w')

# Restore
def enablePrint():
sys.stdout = sys.__stdout__
# 阻止输出
blockPrint()
参考文章:
【1】.OpenCV-Python (官方)中文教程(部分一)
【2】.心得:大疆无人机RTMP推流直播(Windows版本已成功) 这是正常的时候的事情。
【3】.Python logging日志模块配置/使用/禁用
【4】.cv::utils::logging Namespace Reference 这是 opencv 日志枚举文件。
【5】.setLogLevel Currently this API is experimental and it is not exposed into Python.You can try to set OPENCV_LOG_LEVEL=INFO environment variable before loading of OpenCV binaries.
【6】.Introduction 这里有三种设置环境变量的方法
【7】.Enable OpenCV ffmpeg logging
【8】.Unable to disable Opencv FFMPEG error logs 这里用了很多的变量,但是我尝试过都不行。
【9】.How to hide console output of FFmpeg in Python? ffmpeg.input(file).output(filename, loglevel=”quiet”).run()
【10】.屏蔽ffmpeg输出命令(不输出多余信息) -loglevel quiet
【11】.python logging关闭第三方debug日志 1.导入logging模块。2.创建一个Logger对象。3.获取第三方库的Logger对象。4.设置第三方库的Logger级别为WARNING。
【12】.FFmpeg打印日志函数分析 这是用的c语言的部分代码。
【13】.FFMPEG 日志输出控制 av_log_set_level(AV_LOG_QUIET);
【14】.关于python中屏蔽输出
【15】.python小技巧[] 禁用脚本中的print
【16】.如何为OpenCV启用日志记录 这里提供了一个 logging.getLogger(“OpenCV”) ,但是我觉得应该不是这么弄的,我尝试了之后,也不行。

9.配置文件

增加一个 conf 模块,使用的时候就是 conf=conf.getConf()。在一个文件中定义的变量,可以在另外一个文件中访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import os
import sys
import configparser

# 配置
conf=dict({})

# 读取配置
def load_env():
# 读取并设置全局变量
configPath=os.path.abspath(os.path.join(sys.path[0], ".."))
configFile = configPath+'/conf/config.ini'
# 创建配置文件对象
con = configparser.ConfigParser()
# 读取文件
con.read(configFile, encoding='utf-8')
# 获取所有section
items = con.items('common')
items = dict(items)

global conf
conf=items

def getConf():
return conf

load_env()
参考文章:
【1】.python读取配置文件方式(ini、yaml、xml) 这里代码简单。
【2】.Python读取配置文件
【3】.Python全局变量跨模块变量定义和使用 这里设置了多模块共用一个配置文件
【4】.如何写 python 项目 config 配置 这里分为了测试代码和正式环境代码,可以作为参考
【5】.python获取当前运行程序所在目录 1.获取脚本运行所在目录;2.获取当前运行路径;3.脚本文件路径;
【6】.python 获取当前目录 上一级目录 上上一级目录 os.getcwd() 方法获取路径
【7】.超全!Python中常见的配置文件写法 目前常用且流行的配置文件格式类型主要有 ini、json、toml、yaml、xml 等,这些类型的配置文件我们都可以通过标准库或第三方库来进行解析。

10.defaultdict(lambda: [])

我在运行目标识别的时候,很多的文章都有这么一句话,使用的时候就是让我莫名其妙,明明就是没有 track_history[track_id]=”” 这种赋值,为什么就可以直接使用了呢?

1
2
3
4
5
6
# 声明
track_history = defaultdict(lambda: [])

# 使用
track = track_history[track_id]
track.append((float(x), float(y))) # x, y center point

后来我理解是,这个用法如果 “当字典里的键不存在时新建一个带默认值的键” ,这样就好理解了。突然发现新大陆了,这里也就可以解释为,如果 track_history[track_id] 这个值不存在,就返回一个默认的空数组。

参考文章:
【1】.关于lambda在defaultdict中的用法 为了合并“当字典里的键不存在时新建一个带默认值的键”和“运用新建的键加以计算”这两步存在的
【2】.Python 中的預設字典 字典和 defaultdict 的功能幾乎相同,除了 defaultdict 從不引發 KeyError 之外。它為不存在的鍵提供預設值。
【3】.Python collections.defaultdict()与dict的使用和区别 这里的defaultdict(function_factory)构建的是一个类似dictionary的对象,其中keys的值,自行确定赋值,但是values的类型,是function_factory的类实例,而且具有默认值。比如defaultdict(int)则创建一个类似dictionary对象,里面任何的values都是int的实例,而且就算是一个不存在的key, d[key] 也有一个默认值,这个默认值是int类型值0.
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。