Django框架之原始web框架优化

一、web应用框架简介及手撸web框架

软件开发架构详细:网络编程之网络架构及其趋势 - Xiao0101 - 博客园 (cnblogs.com)

软件开发架构分为两种

  • c/s架构:客户端软件(client)—服务端软件(server)
  • b/s架构 :浏览器(Browser)------服务端软件(server)

总结:BS本质上也是CS架构

1、web应用程序是什么?

WEB应用程序一般是B/S模式。Web应用程序首先是“应用程序”,和用标准的程序语言,如C、C++等编写出来的程序没有什么本质上的不同。然而Web应用程序又有自己独特的地方,就是它是基于Web的,而不是采用传统方法运行的。换句话说,它是典型的浏览器/服务器架构的产物。

在这里插入图片描述

本质上:浏览器是一个socket客户端,服务器是一个socket服务端

2、web框架

(1)知识回顾

HTTP协议详细:前端基础之HTTP协议介绍 - Xiao0101 - 博客园 (cnblogs.com)

(2)web框架介绍

Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的。也可以说web框架就是在以上十几行代码基础张扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率。

(3)web框架的本质

所有的Web应用其实就是一个socket服务端, 而用户使用的浏览器就是一个socket客户端程序, 明白了Web框架的本质, 我们就可以实现自己的Web框架了。

(4)根据之前学的知识形成的自定义web框架

import socketserver = socket.socket()  # 默认就是基于网络的TCP协议
server.bind(("127.0.0.1",8080))
server.listen(5)while 1:conn,addr = server.accept()data = conn.recv(1024)print(data)  # 将请求打印出来conn.send(b"HTTP?1.1 200 OK\r\n\nOur destiny is our own!")conn.close()

将服务端运行,客户端访问服务端,运行结果如下:

在这里插入图片描述

HTTP协议规定了让大家发送消息、接收消息的时候有个格式依据以后浏览器发送请求信息也好,服务器回复响应信息也罢,都要按照这个规则来。

pycharm输出结果如下:

# 请求首行
b'GET / HTTP/1.1\r\n# 请求头(都是一大堆的K:V键值对)
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Cache-Control: max-age=0\r\n
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"\r\n
sec-ch-ua-mobile: ?0\r\n
sec-ch-ua-platform: "Windows"\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\nSec-Fetch-User: ?1\r\n
Sec-Fetch-Dest: document\r\nAccept-Encoding: gzip, deflate, br, zstd\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=9qUCCe8NhifmyhgtznpwF9dtBc3Qi3mreGFBPup3hNpwtSNDaGdzpvQACQxUX8Je; sessionid=3o16gvni7tw8kvq01ydx0pwaunvt8r6m\r\n\# 换行 
r\n
'
# 请求体
b'GET /favicon.ico HTTP/1.1\r\n
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"\r\n
sec-ch-ua-mobile: ?0\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36\r\n
sec-ch-ua-platform: "Windows"\r\n
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8\r\n
Sec-Fetch-Site: same-origin\r\n
Sec-Fetch-Mode: no-cors\r\n
Sec-Fetch-Dest: image\r\nReferer: http://127.0.0.1:8080/\r\n
Accept-Encoding: gzip, deflate, br, zstd\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: csrftoken=9qUCCe8NhifmyhgtznpwF9dtBc3Qi3mreGFBPup3hNpwtSNDaGdzpvQACQxUX8Je; sessionid=3o16gvni7tw8kvq01ydx0pwaunvt8r6m\r\n\r\n'

可以说web服务的本质都是基于这简单的套接字程序扩展出来的。

(5)根据不同的路径返回不同的内容

通过以上,我们是实现了一个简易版的web框架

但是存在以下问题:

在用户访问不同网页时候,如何让我们的Web服务根据用户请求的URL不同而返回不同的内容呢?

解决方案:

  • HTTP请求数据

  • /favicon.ico直接忽略 不影响判断

  • 利用字符串切割和索引取值获取相应数据

其实很简单,我们可以从请求相关数据里面拿到请求URL的路径,然后拿路径做一个判断…

'''
根据不同的URL返回不同的内容
'''
import socketserver = socket.socket()  # 默认就是TCP协议
server.bind(('127.0.0.1',8080))
server.listen(5)while True:conn, addr = server.accept()  # 三次四次挥手data = conn.recv(1024)res = data.decode('utf8')conn.send(b'HTTP/1.1 200 OK\r\n\r\n')  # 请求首行,请求头,空行path = res.split(' ')[1]   # 字符串切割获取地址if path == '/index':       # 判断地址# conn.send(b'index')  # 1.如果判断成功则发送请求体with open(r'1.html','rb') as f:  # 2.或者打开文件一内容作为请求体发送data = f.read()conn.send(data)elif path == '/login':   # 1.如果判断为loginconn.send(b'login')  # 2.就发送b'login'的请求体else:conn.send(b'404 error')  # 没匹配到则返回404conn.close()

1.html内容如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>title</title>
</head>
<body><h1 style="color: #31b0d5">嗨,朋友!你来了,你好啊!</h1>
</body>
</html>

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

存在的问题
  • 如果网址路径很多,服务端代码重复(因为if…else…会变得非常多。)
  • 手动处理http数据格式过于繁琐,并且只能拿到url后缀,其他数据获取繁琐
  • 并发的问题
服务器和应用程序

对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。

服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。

应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。

这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。

这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。

WSGI是Python Web应用程序和Web服务器之间的一种标准接口,它定义了一个简单而通用的接口,使得不同的Web应用程序框架(如Flask、Django等)可以与不同的Web服务器(如Apache、Nginx等)进行交互。

常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。

二、基于 wsgiref 模块搭建web框架

1、wsgiref 模块介绍

wsgiref模块是Python标准库中的一个模块,用于实现WSGI(Web Server Gateway Interface)规范。

wsgiref模块提供了一些工具和类,帮助开发者快速构建符合WSGI规范的应用程序和服务器。主要功能包括:

  1. WSGI应用程序开发: wsgiref模块提供了一些类和函数,帮助开发者编写符合WSGI规范的应用程序。开发者可以定义一个WSGI应用程序,接收HTTP请求,并返回HTTP响应。
  2. WSGI服务器实现: wsgiref模块还提供了一个简单的WSGI服务器实现,可以用于在开发和测试阶段运行WSGI应用程序。这样开发者可以在本地快速搭建一个简单的Web服务器来运行和测试他们的应用程序。
  3. 辅助功能: 除了WSGI应用程序和服务器之外,wsgiref模块还提供了一些辅助函数和类,用于处理HTTP请求、构建HTTP响应等操作。

2、使用wsgiref 模块的好处

  • wsgiref模块帮助我们封装了socket 代码

  • 帮我们处理 http 格式的数据

  • 请求来的时候帮助你自动拆分http格式数据并封装成非常方便处理的数据格式(类似于字典)

  • 响应走的时候帮你将数据再打包成符合http格式的数据

3、实现代码

from wsgiref.simple_server import make_server# 以函数形式定义功能,扩展方便
def index_func(request):return 'index'def login_func(request):return 'login'def error(request):return '404 Not found'# 地址与功能的对应关系
urls = [('/index', index_func),('/login', login_func)
]def run_server(request, response):"""函数名定义什么都无所谓,这里我们使用run_server:param request:请求相关的所有数据,一个类似字典的形式,"PATH_INFO"正好就是我们要找的地址wsgiref模块帮我们处理好HTTP格式的数据,封装成了字典让你更加方便的操作:param response:响应相关的所有数据:return:返回给浏览器的数据,返回格式必须是'return [二进制格式的数据]' 这种样式"""response('200 OK', [])  # 响应首行, 响应头current_path = request.get("PATH_INFO")  # 找到路径func = None  # 定义一个变量, 存储匹配到的函数名for url in urls:if current_path == url[0]:func = url[1]  # 如果匹配到了则将函数名赋值给funcbreak  # 匹配之后立刻结束循环if func:  # 然后判断一下func是否被赋值了(也就是是否匹配到了)data = func(request)  # 执行函数拿到结果,request可有可无,但放进去以后好扩展else:data = error(request)return [data.encode('utf-8')]if __name__ == '__main__':server = make_server('127.0.0.1', 8080, run_server)  # 一旦被访问将会交给run_server处理'''会实时监听127.0.0.1:8080地址,只要客户端来了都会交给run函数处理(加括号触发run函数的运行)flask启动源码make_server('127.0.0.1',8080,obj)__call__'''server.serve_forever()  # 启动服务端并一直运行

产生的问题

  • 网址很多的情况下如何匹配
  • 网址多匹配如何解决
  • 功能复杂代码块如何解决

看起来上面的代码还是要挨个写if判断,怎么办?

三、封装处理优化

1、根据功能划分模块

  • 根据功能的不同拆分成不同的py文件

(1)views.py

  • 存储路由与函数对应关系
# 功能函数
def register(request):return 'register'def login(request):return 'login'def index(request):return 'index'def error(request):with open(r'templates/error.html', 'r', encoding='utf8') as f:return f.read()

(2)urls.py

  • 存放路径与功能的对应关系
from views import *# 后缀匹配
urls = (('/register', register),('/login', login),('/index', index),
)

(3)server.py

  • 存储启动及分配代码
from wsgiref.simple_server import make_server
from urls import urls
from views import *def run_server(request,response):""":param request:请求相关的所有数据,一个类似字典的形式,"PATH_INFO"正好就是我们要找的地址:param response:响应相关的所有数据:return:"""response('200 OK',[])  # 响应首行, 响应头current_path = request.get("PATH_INFO")  # 找到路径func = None  # 定义一个变量, 存储匹配到的函数名for url in urls:if current_path == url[0]:func = url[1]  # 如果匹配到了则将函数名赋值给funcbreak  # 匹配之后立刻结束循环if func:  # 然后判断一下func是否被赋值了(也就是是否匹配到了)data = func(request)  # 执行函数拿到结果,request可有可无,但放进去以后好扩展else:data = error(request)return [data.encode('utf-8')]if __name__ == '__main__':server = make_server('127.0.0.1', 8080, run_server)  # 一旦被访问将会交给run_server处理server.serve_forever()  # 启动服务端并一直运行

总结:

拆分后好处在于要想新增一个功能,只需要在views.py中编写函数,urls.py添加对应关系即可

2、模板文件与静态文件

(1)templates文件夹

  • 存储html文件

(2)static文件夹

  • 存储html页面所需静态资源

四、返回动静态页面

1、静态网页

  • 页面上的数据是直接写死的,万年不变
  • 如果不想仅仅返回几个字符串, 而是想给浏览器返回完整的HTML内容, 对此我们只需要通过 open 打开 HTML文件将内容读出来再发送给浏览器就行了
# 静态网页制作
def login_func(request):with open(r"./login.html", "r", encoding="utf-8")as f:res = f.read()  # 打开文件读出内容,再返回文件内容return res

2、动态网页

  • 数据是实时获取的
    • 后端获取当前时间展示到html页面上
    • 数据是从数据库中获取的展示到html页面上
# 动态网页制作
def get_time(env):current_time = datetime.datetime.now().strftime('%Y-%m-%d %X')# 如何将后端获取到数据"传递"给html文件?with open(r'templates/03 mytime.html', 'r', encoding='utf8') as f:data = f.read()# 得到的data就是一堆字符串data = data.replace('fwefwef', current_time)  # 在后端将html页面处理好之后再返回给前端return data

3、练习

将一个字典传递给html文件,并且可以在文件上方便快捷的操作字典数据

def get_dict(env):user_dic = {'username': 'xiao', 'age': 18}with open(r'templates/04 get_dict.html','r',encoding='utf8') as f:data = f.read()tmp = Template(data)res = tmp.render(user=user_dic)# 给get_dict.html传递了一个值,页面上通过变量名user就能够拿到user_dictreturn res

五、模版语法之Jinja2

举例演示模版语法与之前的后端到前端传输局方式的不同

1、原始方式

  • 页面展示当前时间

(1)后端

def get_time(request):# 1.获取当前时间import timec_time = time.strftime('%Y-%m-%d %X')# 2.读取html文件with open(r'templates/get_time.html','r',encoding='utf8') as f:data = f.read()# 3.思考:如何给字符串添加一些额外的字符串数据>>>:字符串替换new_data = data.replace('random_str',c_time)return new_data

(2)前端

<h1>展示后端获取的时间数据</h1>
<span>random_str</span>

2、jinja2模板语法

(1)下载安装

  • 第三方模块需要先下载后使用
pip3 install jinja2

(2)功能和语法

① 功能

支持将数据传递到html页面并提供近似于后端的处理方式简单快捷的操作数据

② 语法

变量插值: 使用双大括号{{ }}来插入变量值到模板中。

Hello, {{ name }}!

表达式: 可以在{{ }}中使用表达式。

{{ 2 + 2 }}

**过滤器:**使用管道符|应用过滤器对变量进行处理。

{{ name|capitalize }}

控制结构: 使用{% %}来表示控制结构,如条件语句和循环。

{% if condition %}Content to show if condition is true.
{% endif %}
{% for item in items %}{{ item }}
{% endfor %}

模板继承: 使用{% extends %}{% block %}来实现模板继承和重写。

{% extends "base.html" %}{% block content %}Content specific to this template.
{% endblock %}

宏(Macro): 定义可重用的代码块。

{% macro input(name, value='') %}<input type="text" name="{{ name }}" value="{{ value }}">
{% endmacro %}

(3)views.py

from jinja2 import Template
def get_dict(request):user_dict = {'name': 'xiao', 'pwd': 123, 'hobby': 'read'}new_list = [11, 22, 33, 44, 55, 66]with open(r'templates/get_dict.html', 'r', encoding='utf8') as f:data = f.read()temp_obj = Template(data)res = temp_obj.render({'user':user_dict,'new_list':new_list})return res

(4)templates

  • –get_dict.html
<h1>字典数据展示</h1>
<p>{{ user }}</p>
<p>{{ user.name }}</p>
<p>{{ user['pwd'] }}</p>
<p>{{ user.get('hobby') }}</p>
<h1>列表数据展示</h1>
<p>{% for i in new_list%}<span>元素:{{ i }}</span>{% endfor %}
</p>
pip install jinja2
"""模版语法是在前端起作用的,后端不支持"""# 模版语法
{{ user }}
{{ user.get('username') }}
{{ user.age }}
{{ user['hobby'] }}{% for user_dict in user_list %}<tr><td>{{ user_dict.id}}</td><td>{{ user_dict.username}}</td><td>{{ user_dict.password}}</td><td>{{ user_dict.hobby}}</td></tr>
{% endfor %}

六、自定义简易版本web框架请求流程图

在这里插入图片描述

流程图流程

浏览器客户端wsgiref模块请求来:处理浏览器请求,解析浏览器HTTP格式的数据,封装成大字典(PATH_INFO中存放的用户访问资源的路径)响应去:将数据打包成符合HTTP格式,在返回给浏览器后端:urls.py:找出用户输入的路径有么有与视图层的对应关系,如果有则取到views.py找对应的视图函数。view.py:功能1(静态):视图函数找templates中的html文件,返回给wsgiref做HTTP格式的封装处理,再返回给浏览器.功能2(动态):视图函数通过pymysql链接数据库, 通过jinja2模板语法将数据库中取出的数据在tmpelates文件夹下的html文件做一个数据的动态渲染, 最后返回给wsgiref做HTTP格式的封包处理, 再返回给浏览器.功能3(动态):也可以通过jinja2模板语法对tmpelates文件夹下的html文件进行数据的动态渲染, 渲染完毕, 再经过wsgiref做HTTP格式的封包处理, 再返回给浏览器.templates:html文件数据库

七、总结

1、urls.py

  • 后缀与函数名对应关系
    • (‘/index’,register)
    • 后缀专业名词称之为’路由’
    • 函数名专业名词称之为’视图函数’
    • urls.py专业名词称之为’路由层’

2、views.py

  • 专门编写业务逻辑代码
    • 可以是函数 也可以是类
    • 函数专业名词称之为’视图函数’
    • 类专业名词称之为’视图类’
    • views.py专业名词称之为’视图层’

3、templates文件夹

  • 专门存储html文件
  • html文件专业名词称之为’模板文件’
  • templates文件夹专业名词称之为’模板层’

4、static文件夹

  • 专门存储静态文件资源
    • 页面所需css文件、js文件、图片文件、第三方文件可统称为’静态资源’

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

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

相关文章

电子负载仪的远端控制

前言 最近研究了电子负载仪的远端控制&#xff08;区别于前面板控制&#xff09;&#xff0c;主要是用于程序控制&#xff0c;避免繁琐复杂的人工控制&#xff0c;举了南京嘉拓和艾维泰科的例子。 有纰漏请指出&#xff0c;转载请说明。 学习交流请发邮件 1280253714qq.com …

今日arXiv最热大模型论文:大模型也来看球,还能判断是否犯规

在足球世界&#xff0c;裁判的哨声可谓“千金难买”&#xff0c;因为它能直接决定俱乐部的钱包是鼓是瘪。但球场变化莫测&#xff0c;非常考验裁判的水平。 2022年卡塔尔世界杯上&#xff0c;半自动越位识别技术&#xff08;SAOT&#xff09;闪亮登场&#xff0c;通过12台摄像…

玩转nginx的配置文件3

1. limit_req_zone配置限流 limit_req_zone $binary_remote_addr zonemylimit:10m rate10r/s;upstream myweb {server 10.0.105.196:80 weight1 max_fails1 fail_timeout1;}server {listen 80;server_name localhost;location /login {limit_req zonemylimit;proxy_pass http:…

总结反思 持续进步-开源即时通讯(IM)项目OpenIM 新版本release-v3.7发布

背景 过去&#xff0c;我们团队对开源项目的认知较浅&#xff0c;过分追求进度&#xff0c;而忽视了代码的质量和规范。这导致了一些问题&#xff0c;例如部署流程设计不当&#xff1a;流程复杂、不规范&#xff0c;以及Mac与Windows部署的明显缺陷。这些问题不仅给开发者带来了…

Android Studio初学者实例:RecyclerView学习--模仿今日头条

本案例来自于学校的一个简单的课程实验 先看效果图&#xff0c;可以显然的看到&#xff0c;一些item是不同的布局&#xff0c;而其他布局就是简单的布局嵌套 看一下xml代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout …

抽象的代理模式1.0版本

前言&#xff1a; 在阅读Spring Security官方文档时&#xff0c;里面设计到了一种设计模式——代理模式Proxy 众里寻她千百度&#xff0c;蓦然回首&#xff0c;那人却在灯火阑珊处 开始 在之前的文章里陈述了一个观点——编程语言和语言没有区别 现看看我们日常生活中的代理…

[笔试训练](七)

目录 019&#xff1a;字符串中找出连续最长的数字串 020&#xff1a;岛屿数量 021&#xff1a;拼三角 019&#xff1a;字符串中找出连续最长的数字串 字符串中找出连续最长的数字串_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 边遍历边记下遇到的…

ionic 中对Input输入框、searchbar进行solr检索

一、概述 Ionic 是一个用于开发跨平台应用程序的开源工具&#xff0c;可以使用 Angular、React 或 Vue 等前端框架。要在 Ionic 应用程序中实现实时与 Solr 通信&#xff0c;可以使用 HTTP 客户端&#xff08;如 Angular 的 HttpClient 或 Ionic 的 Native HTTP&#xff09;…

鸿蒙入门11-DataPanel组件

数据面板组件 用于将多个数据的占比情况使用 占比图 进行展示 参数 参数形式 &#xff1a; DataPanel( options:{ values: number[], max?: number, type?: DataPanelType } ) 参数名 参数类型 是否必填 默认值 参数描述 values number[] 是 - 数据值列表 最大支持…

Feign功能详解、使用步骤、代码案例

简介&#xff1a;Feign是Netflix开发的声明式&#xff0c;模板化的HTTP客户端&#xff0c;简化了HTTP的远程服务的开发。Feign是在RestTemplate和Ribbon的基础上进一步封装&#xff0c;使用RestTemplate实现Http调用&#xff0c;使用Ribbon实现负载均衡。我们可以看成 Feign R…

IDEA快速入门

目录 1. 概述 2. 安装 3. 激活 4. 关闭自动更新 5. 创建Java项目 5.1 配置JRE 5.2 创建项目 6. 配置设置 6.1 主题 6.2 设置字体默认大小 6.3 鼠标滚轮改变字体大小 6.4 设置自动导入 6.5 项目选择 7. lombok插件 7.1 安装插件 7.2 启用注解 8. 安装包及插件…

linux-进程(2)

1.通过系统调用获取进程标示符 进程id&#xff08;PID&#xff09; 父进程id&#xff08;PPID&#xff09; 每一个可执行程序运行起来之后都会成为一个进程&#xff0c;每个进程都有一个自己的id&#xff0c;以及一个父进程id&#xff0c;父进程就是创建自己进程的进程&#xf…

一条龙-T检验+绘制boxplot

1.输入文件&#xff1a; 2.代码 #title:boxplot-5utr-cds-3tr-ATCG的百分比分布和T检验_封装函数版 rm(listls(allTRUE)) setwd("E:/R/Rscripts/5UTR_ABD_TE") library(tidyverse) library(ggplot2) # library(RColorBrewer) library(patchwork) library(dplyr) l…

Python-100-Days: Day01

Day01 Python简介 1.1989年Guido von Rossum在圣诞节之夜开始着手python语言编译器的编写。 2.1991年2月 Python v1 编译器诞生&#xff0c;使用C实现的&#xff0c;此时可以调用C的库函数。 3.1994年1月&#xff0c;Python v1.0 正式版发布。 4.2000年10月16日&#xff0…

新药品注册分类5大类的注册标准

在医药行业的浩瀚海洋中&#xff0c;药品注册分类就如同一座明亮的航标灯&#xff0c;指引着每一款新药从实验室走向市场&#xff0c;从理论概念变成患者手中的生命希望。本文将深入探讨化学药、中药、生物药的药品注册分类标准&#xff0c;药品分类常见问题、以及如何高效查询…

linux系统-深入学习文件系统与日志分析

目录 一、inode于block inode于block概括inode的内容inode包含文件的元信息用stat命令可以查看某个文件的inode信息Linux系统文件三个主要的时间属性目录文件架构 用户通过文件名打开文件时&#xff0c;系统内部的过程查看inode号码的实操硬盘分区后的结构 &#x1f447;用户访…

走向大规模应用之前,DePIN 如何突破技术、数据与市场之网

近期&#xff0c;随着分布式物理基础设施网络&#xff08;DePIN&#xff09;的快速演变&#xff0c;一个旨在利用区块链技术彻底改造传统基础设施模型的新兴生态系统正在逐渐浮现。2024 年 4 月&#xff0c;以 peaq 为代表的 DePIN 项目成功筹集了 1500 万美元用于生态系统的扩…

mac配置maven

在 macOS 上配置 Maven 也相对简单。以下是一种常用的方法&#xff1a; 1. 安装maven **下载 Maven&#xff1a;**首先&#xff0c;你需要从 Maven 官网&#xff08;https://maven.apache.org/download.cgi&#xff09;下载最新版本的 Maven。你可以选择二进制压缩包&#xf…

02.Scala简单演示

Scala创建对象的方法与Java有所不同 class可以直接传入形参&#xff1b; 形式为 变量名称&#xff1a;变量类型 逗号隔开 ** ** 方法定义也比较特殊 ** ** def方法名&#xff08;&#xff09;:返回值 { } 其中返回值Unit 等价于Java中的void

系统服务(22年国赛)—— 磁盘管理(压缩去重)

前言&#xff1a;原文在我的博客网站中&#xff0c;持续更新数通、系统方面的知识&#xff0c;欢迎来访&#xff01; 系统服务&#xff08;22年国赛&#xff09;—— 磁盘管理(压缩&&去重)https://myweb.myskillstree.cn/90.html 目录 StorageSrv 安装并创建vdo 将…