1、使用多进程 multiprocesssing
2、使用C扩展
3、使用异步编程
4、使用外部库如Numpy、Panda
5、GIL优化:python版本升级,可能会进行优化
Python 使用自动内存管理来回收不再使用的对象,这主要通过垃圾收集器(Garbage Collector,GC)来实现。Python 的垃圾收集器主要依赖于引用计数机制和循环垃圾收集机制。
引用计数
Python 中的每个对象都有一个引用计数,用来记录有多少个引用指向该对象。当一个对象的引用计数变为 0 时,意味着没有任何引用指向该对象,该对象可以被垃圾收集器立即回收。
引用计数机制简单有效,但也有一些局限性:
- 循环引用问题:如果两个或多个对象相互引用,它们的引用计数永远不会变为 0,即使它们不再被使用。
- 内存泄漏:如果程序中存在无法访问到的对象,即使它们不再被使用,也不会被回收。
循环垃圾收集
为了解决循环引用问题,Python 使用了循环垃圾收集机制。这是一种基于标记-清除(Mark-and-Sweep)算法的垃圾收集方法。
- 标记阶段:垃圾收集器遍历所有可达的对象,并将它们标记为活跃的。
- 清除阶段:垃圾收集器遍历所有未被标记的对象,并将它们回收。
Python 的循环垃圾收集器可以检测到循环引用,并能够回收这些无法通过引用计数机制回收的对象。
垃圾收集器的触发
Python 的垃圾收集器不是在每次对象不再使用时就立即触发,而是在以下情况下触发:
- 程序显式调用
gc.collect()
函数。- 程序达到一定的内存使用阈值。
- 程序启动时或退出前。
- 1、使用模块
- Python 的模块本身就是一个单例。模块在第一次导入时会被初始化,之后再次导入时会使用已经初始化的模块。
- # my_singleton_module.py
- class Singleton:
- def __init__(self):
- self.value = 'I am a singleton'
-
- # 使用
- from my_singleton_module import Singleton
- singleton_instance = Singleton()
-
- 2、使用装饰器
- def singleton(cls):
- instances = {}
- def wrapper(*args, **kwargs):
- if cls not in instances:
- instances[cls] = cls(*args, **kwargs)
- return instances[cls]
- return wrapper
-
- @singleton
- class MyClass:
- def __init__(self):
- self.value = 'I am a singleton'
-
- # 使用
- instance1 = MyClass()
- instance2 = MyClass()
- print(instance1 is instance2) # True
-
- 3、使用类属性
- class Singleton:
- _instance = None
-
- def __new__(cls):
- if cls._instance is None:
- cls._instance = super(Singleton, cls).__new__(cls)
- return cls._instance
-
- def __init__(self):
- self.value = 'I am a singleton'
-
- # 使用
- instance1 = Singleton()
- instance2 = Singleton()
- print(instance1 is instance2) # True
-
-
- 4、使用元类
- class SingletonMeta(type):
- _instances = {}
- def __call__(cls, *args, **kwargs):
- if cls not in cls._instances:
- instance = super().__call__(*args, **kwargs)
- cls._instances[cls] = instance
- return cls._instances[cls]
-
- class Singleton(metaclass=SingletonMeta):
- def __init__(self):
- self.value = 'I am a singleton'
-
- # 使用
- instance1 = Singleton()
- instance2 = Singleton()
- print(instance1 is instance2) # True
Python 支持多进程、多线程和协程三种并发执行的机制,它们各自有不同的特点和用途:
多进程(Multiprocessing)
- 定义:多进程是指操作系统为每个进程分配独立的内存空间,进程之间不共享内存。
- 优点:
- 隔离性好:一个进程崩溃不会影响其他进程。
- 利用多核CPU:可以充分利用多核处理器的计算能力,因为每个进程可以运行在不同的CPU核心上。
- 缺点:
- 创建和销毁进程的开销大。
- 进程间通信(IPC)复杂且成本高。
- 适用场景:适合CPU密集型任务,或者需要隔离性的场景。
多线程(Multithreading)
- 定义:多线程是指在一个进程中并行运行多个线程,线程之间共享进程的内存空间。
- 优点:
- 资源共享:线程间可以共享数据,这使得线程间通信更加容易。
- 创建和切换开销小。
- 缺点:
- Python中的全局解释器锁(GIL):在CPython实现中,由于GIL的存在,同一时刻只有一个线程可以执行Python字节码,这限制了多线程在CPU密集型任务中的并行性。
- 线程安全问题:需要同步机制来避免竞态条件和数据不一致。
- 适用场景:适合I/O密集型任务,或者需要共享内存资源的场景。
协程(Coroutines)
- 定义:协程是一种更轻量级的执行单元,它在用户态进行调度,而不是操作系统内核态。
- 优点:
- 高效:协程的创建和切换开销非常小。
- 非抢占式:协程的执行是协作式的,一个协程执行完成后主动让出控制权给另一个协程。
- 适用于大量I/O操作:协程可以在等待I/O操作时挂起,让其他协程运行,提高效率。
- 缺点:
- 调试困难:协程的调用栈可能不如线程和进程那样直观。
- 错误处理:协程的错误可能会影响到整个程序的执行流程。
- 适用场景:适合处理大量I/O密集型任务,如网络请求、文件操作等。
总结
- 多进程:适合CPU密集型任务,可以充分利用多核处理器,但进程间通信复杂。
- 多线程:适合I/O密集型任务,线程间可以共享内存,但在CPython中由于GIL的限制,多线程在CPU密集型任务中的并行性受限。
- 协程:适合大量I/O操作,可以在等待I/O时让出控制权,提高程序的响应性和效率。
在Python中,可以使用
multiprocessing
模块来创建和管理多进程,使用threading
模块来创建和管理多线程,使用asyncio
库来创建和管理协程。协程在Python 3.5之后得到了原生支持,通过async
和await
关键字实现。
1、外层方法的返回是对内部方法的调用
from multiprocessing import Process from concurrent.futures import ProcessPoolExecutor
web -> wsgi -> process_request -> process_view -> view -> process_response -> wsgi -> web
如果有多个中间件,ABCDE(C是视图),执行过程是
执行ABDE的process_request
执行view逻辑
执行EDBA的process_response
docker exec -it
/bin/bash
# 启动一个容器
docker run -d --name new_container my_new_image
# 进入一个运行中的容器
docker exec -it my_container /bin/bash
# 交付容器,创建一个新的镜像
docker commit my_container my_new_image
docker run --rm -d --name my_container ubuntu sleep 60
-rm:容器停止时自动销毁
#
# 在dockerfile中设置cmd
FROM ubuntu
# ... 其他指令 ...# 定义一个清理脚本
COPY cleanup.sh /cleanup.sh
RUN chmod +x /cleanup.sh# 设置容器退出时执行清理脚本
CMD ["/cleanup.sh"]
FROM - 指定基础镜像,所有的构建过程都是基于这个镜像开始的。
FROM ubuntu:18.04
RUN - 执行命令,通常用于安装软件包或执行脚本。
RUN apt-get update && apt-get install -y curl
CMD - 容器启动时默认执行的命令。如果有多个 CMD 指令,只有最后一个会生效。
CMD ["python", "app.py"]
ENTRYPOINT - 容器启动时要运行的可执行文件,可以与 CMD 组合使用。
ENTRYPOINT ["python"]
EXPOSE - 声明容器运行时监听的端口,不会发布端口,只是作为文档说明使用。
EXPOSE 80
ENV - 设置环境变量。
ENV PATH /usr/local/nginx/bin:$PATH
ADD - 将文件、目录或远程文件URL添加到容器中。
ADD source_file.txt /dest/path
COPY - 类似于 ADD,但只支持本地文件的复制。
COPY source_file.txt /dest/path
VOLUME - 创建一个可以从本地主机或其他容器挂载的挂载点。
VOLUME /data
WORKDIR - 设置工作目录,即容器内部的当前目录。
WORKDIR /app
USER - 设置运行容器时的用户名或 UID。
USER nobody
ARG - 构建参数,可以在构建时通过
--build-arg
传递给 Docker。
ARG VERSION=1.0
ONBUILD - 设置触发器,当以当前镜像为基础镜像时,自动执行的指令。
ONBUILD RUN echo "Hello, this is an ONBUILD trigger"
STOPSIGNAL - 设置停止容器时使用的系统调用信号。
STOPSIGNAL SIGKILL
LABEL - 添加元数据到镜像,可以是键值对。
LABEL maintainer="name@example.com"
HEALTHCHECK - 设置健康检查命令,用于确定容器是否健康。
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1
启动服务: 使用
up
命令启动在docker-compose.yml
文件中定义的所有服务。
docker-compose up
启动服务(后台运行): 添加
-d
标志以在后台运行服务。
docker-compose up -d
停止服务: 使用
down
命令停止所有由docker-compose.yml
文件定义的服务,并移除容器、网络、卷和镜像。
docker-compose down
查看服务状态: 使用
ps
命令查看所有服务的容器状态。
docker-compose ps
查看日志: 使用
logs
命令查看服务的日志输出。
docker-compose logs
重新启动服务: 使用
restart
命令重新启动服务。
docker-compose restart
停止并移除容器: 使用
stop
命令停止服务中的所有容器。
docker-compose stop
构建或重建服务: 使用
build
命令重新构建或构建服务。
docker-compose build
拉取服务的镜像: 使用
pull
命令拉取服务的镜像。
docker-compose pull
运行一次性命令: 使用
run
命令在服务的容器中运行一次性命令。
docker-compose run myservice /bin/bash
查看服务详情: 使用
config
命令查看docker-compose.yml
文件的配置详情。
docker-compose config
扩展服务: 使用
scale
命令扩展服务的容器数量。
docker-compose up --scale myservice=3
列出所有容器: 使用
ls
命令列出所有由docker-compose.yml
文件管理的容器。
docker-compose ls
推送服务的镜像: 使用
push
命令推送服务的镜像到远程仓库。
docker-compose push
创建服务的网络: 使用
create-network
命令创建网络。
docker-compose create-network
创建并启动服务: 使用
up
命令创建并启动服务,如果服务已经存在则只启动服务。l
docker-compose up --create
string list set zset hash