当前位置: 首页 > news >正文

Flask项目搭建及部署 —— Python

flask搭建及部署
pip 19.2.3

python 3.7.5

Flask 1.1.1

Flask-SQLAlchemy 2.4.1

Pika 1.1.0

Redis 3.3.11

flask-wtf 0.14.2

1、创建flask项目:
 

创建完成后整个项目结构树: 

app.py: 项⽬管理⽂件,通过它管理项⽬。

static: 存放静态文件

templates文件夹:用于放置html模板文件

由于flask属于轻量级web框架, 更加自由、灵活,可扩展性强,第三方库的选择面广,开发时可以结合自己最喜欢用的轮子,也能结合最流行最强大的Python库 。所以这个框架的代码架构需要自己设计。

2、创建项目主要逻辑代码保存目录

手动创建application目录、filter目录及其子目录

application : 项目主要逻辑代码保存目录

_init_.py : 创建flask应用并加载配置,如mysql,redis,rabbitmq,

apps : 专门用于保存每一个项目的蓝图

app1 : app1蓝图目录,在app1下的init_.py中文件中创建蓝图对象,view.py中新增对应的视图文件,在 model.py中写模型代码

settings : 项目配置存储目录

dev.py : 项目开发阶段配置文件

prop.py : 项目生成阶段配置文件

static : 项目静态文件夹(用于存放css一类的文件)

templates : 用于放置html模板文件

filter : 整个项目拦截器目录

requestFilter.py: 针对整个app项目全局路由拦截规则定义

app.py : 项⽬管理⽂件,通过它启动整个项目

2.1 配置mysql数据库,加载配置文件并针对整个app项目定义全局db
2.1.1 settings.py

#全局通用配置类
class Config(object):"""项目配置核心类"""#调试模式DEBUG=False
​# 配置日志# LOG_LEVEL = "DEBUG"LOG_LEVEL = "INFO"
​
​# 配置redis# 项目上线以后,这个地址就会被替换成真实IP地址,mysql也是REDIS_HOST = 'your host'REDIS_PORT = your portREDIS_PASSWORD = 'your password'REDIS_POLL = 10
​#数据库连接格式SQLALCHEMY_DATABASE_URI = "mysql+pymysql://user:password@localhost:3306/test?charset=utf8"# 动态追踪修改设置,如未设置只会提示警告SQLALCHEMY_TRACK_MODIFICATIONS = False# 查询时会显示原始SQL语句SQLALCHEMY_ECHO = False# 数据库连接池的大小SQLALCHEMY_POOL_SIZE=10#指定数据库连接池的超时时间SQLALCHEMY_POOL_TIMEOUT=10# 控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。SQLALCHEMY_MAX_OVERFLOW=2
​
​#rabbitmq参数配置RABBITUSER="user"RABBITPASSWORD="password"RABBITHOST="your ip"RABBITPORT=your port

2.1.2 dev.py

from . import Config
​
class DevelopmentConfig(Config):'开发模式下的配置'# 查询时会显示原始SQL语句SQLALCHEMY_ECHO = True

2.1.3 prop.py

from . import Config
​
class ProductionConfig(Config):"""生产模式下的配置"""DEBUG = False

2.1.4 加载配置文件,定义全局的db( SQLALchemy类的实例 )供项目使用

# 主应用的根目录
app = Flask(__name__)
​
config = {'dev': DevelopmentConfig,'prop': ProductionConfig,
}
​
# 设置配置类
Config = config['dev']
​
# 加载配置
app.config.from_object(Config)
​
# 创建数据库连接对象
db = SQLAlchemy(app)

dev : 测试环境配置

prop: 生产环境配置

Flask应用app配置加载

通常三种方式

从配置对象中加载:app.config.from_object()

从配置文件中加载:app.config.from_pyfile()-ini文件

从环境变量中加载:app.config.from_envvar()

配置对象

从配置对象中加载,创建配置的类:

# 配置对象,里面定义需要给 APP 添加的一系列配置
class Config(object):DEBUG = True
​
​
app = Flask(__name__)
​
# 从配置对象中加载配置
app.config.from_object(Config)
app.run()

配置文件

从配置文件中加载,在目录中定义一个配置文件config.ini

app = Flask(__name__)
​
# 从配置对象中加载配置
app.config.from_pyfile("config.ini")
app.run()

环境变量

app = Flask(__name__)
# 从环境变量中加载
app.config.from_envvar("FLASKCONFIG")
app.run()

2.2 定义model模型,负责和数据库交互
app1.model

from application import db
​
class Wdtest(db.Model):__tablename__ = "wdtest" #设置表名id = db.Column(db.String(100), primary_key=True, comment="主键ID")name = db.Column(db.String(20), index=True, comment="姓名" )age = db.Column(db.Integer, default=True, comment="年龄")

模型 表示程序使用的持久化实体. 在Flask-SQLALchemy 中, 模型一般是一个 Python 类, 类中的属性对应数据库中的表.

db.Model :创建模型,

db.Column : 创建模型属性.

tablename :指定表名

模型属性类型 :

类型名Python类型说明
Integerint普通整数,一般是 32 位
SmallIntegerint取值范围小的整数,一般是 16 位
Big Integerint 或 long不限制精度的整数
Floatfloat浮点数
Numericdecimal.Decimal定点数
Stringstr变长字符串
Textstr变长字符串,对较长或不限长度的字符串做了优化
Unicodeunicode变长 Unicode 字符串
Unicode Textunicode变长 Unicode 字符串,对较长或不限长度的字符串做了优化
Booleanbool布尔值
Datedatetime.date日期
Timedatetime.time时间
DateTimedatetime.datetime日期和时间
Intervaldatetime.timedelta时间间隔
Enumstr一组字符串
PickleType任何 Python 对象自动使用 Pickle 序列化
LargeBinarystr二进制文件


常用 SQLAlchemy 列选项

选项名说明
primary_key如果设为 True,这列就是表的主键
unique如果设为 True,这列不允许出现重复的值
index如果设为 True,为这列创建索引,提升查询效率
nullable如果设为 True,这列允许使用空值;如果设为 False,这列不允许使用空值
default为这列定义默认值

2.3 声明蓝图
app1._init.py

#给app取别名为 'index'
index_blu=Blueprint('index',__name__,template_folder='templates',static_folder='static')
​
from .views import *

template_folder:指定模板文件路径,查找顺序,先全局templates里面找,没找到,再往子蓝图里面找.

这里是把view中所有的视图都声明在index这个蓝图里面,接下来我们需要做的是将这个声明好的蓝图,注册进我们的项目中。

2.4 将声明好的蓝图注册进app中
application.init_:

from application.settings.dev import DevelopmentConfig
from application.settings.prop import ProductionConfig
​
# 主应用的根目录
app = Flask(__name__)
​
config = {'dev': DevelopmentConfig,'prop': ProductionConfig,
}
​
# 设置配置类
Config = config['dev']
​
# 加载配置
app.config.from_object(Config)
​
# 创建数据库连接对象
db = SQLAlchemy(app)
​
# todo 注册蓝图
from .apps.app1 import index_blu
app.register_blueprint(index_blu, url_prefix='/index')

针对:app = Flask(name)解释

Flask类初始化参数

Flask类init方法部分代码

def __init__(self,import_name,static_url_path=None,static_folder="static",static_host=None,host_matching=False,subdomain_matching=False,template_folder="templates",instance_path=None,instance_relative_config=False,root_path=None,):pass

import_name:Flask程序所在的包(模块),传 __name__

static_url_path:静态文件访问路径,可以不传,默认为:/ + static_folder

static_folder:静态文件存储的文件夹,可以不传,默认为 static

template_folder:模板文件存储的文件夹,可以不传,默认为 templates

3 通过以上的步骤后,我们可以基本操作数据库了:
以下所有示例代码,皆在view.py中去实现

3.1 增:
先写怎么增,然后增加,最后提交

student = Wdtest(id=ids , name=name, age=age)
try:application.db.session.add(student)application.db.session.commit()
except:# 事務回滾application.db.session.rollback()

3.2 删:
先获取数据库中的这个数据,再删除它

 user = Wdtest.query.first()application.db.session.delete(user)application.db.session.commit()

3.3 改:

user = Wdtest.query.first()
user.name = name
try:application.db.session.commit()
except:# 事務回滾application.db.session.rollback()

3.4 查:

# 查询所有⽤户数据
user_list=Wdtest.query.all()
​
# 查询有多少个⽤户
user_list_num=Wdtest.query.count()
# 查询第1个⽤户
user=Wdtest.query.first()
# 查询id为3的⽤户[3种⽅式]
user=Wdtest.query.get(3)  # 根据主键查询
user_list=Wdtest.query.filter_by(id=3).all()  # 以关键字实参形式进行匹配字段
user_list=Wdtest.query.filter(Wdtest.id == 3).all()  # 以恒等式形式匹配字段
​
# 查询名字结尾字符为g的所有⽤户
Wdtest.query.filter(Wdtest.name.endswith('g')).all()
​
# 查询名字包含‘wa'的所有项目
user_list=Wdtest.query.filter(Wdtest.name.contains('wa')).all()
# 模糊查询
user_list =Wdtest.query.filter(Wdtest.name.like('%a%')).all()
# 查询名字wa开头和age为20的所有⽤户[2种⽅式]
user_list=Wdtest.query.filter(Wdtest.name.startswith('wa'),Wdtest.age == 20).all()
user_list=Wdtest.query.filter(and_(Wdtest.name.startswith('wa'), Wdtest.age == 20)).all()
​
# 非条件查询查询名字不等于wade的所有⽤户[2种⽅式]
user_list=Wdtest.query.filter(not_(Wdtest.name == 'wade')).all()
user_list=Wdtest.query.filter(Wdtest.name != 'wade').all()
​
# in 条件查询
user_list=Wdtest.query.filter(Wdtest.id.in_(['97124f50-0208-11ea-a66c-04ea56212bdf', '3'])).all()
​
# 所有⽤户先按年龄从⼩到⼤, 再按id从⼤到⼩排序, 取前5个
user_list=Wdtest.query.order_by(Wdtest.age,Wdtest.id.desc()).limit(5).all()
​
# 分⻚查询, 每⻚3个, 查询第2⻚的数据
pn = Wdtest.query.paginate(2,3)
print(pn.pages)
print(pn.page)
print(pn.items)

4 路由传参
有时我们需要将同一类 URL 映射到同一个视图函数处理,比如:使用同一个视图函数来显示不同用户的个人信息。

# 路由传递参数
@app.route('/user/<id>')
def user_info(id):return '%s' % id

路由传递的参数默认当做 string 处理

####指定请求方式

在 Flask 中,定义一个路由,默认的请求方式为:

GET

OPTIONS

HEAD

在装饰器添加请求指定方式:

@app.route('/test', methods=['GET', 'POST'])
def test():return "ok"

5 动态正则匹配路由
flask实现正则匹配步骤:

导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录

自定义转换器:自定义类继承于转换器基类

添加转换器到默认的转换器字典中

使用自定义转换器实现自定义匹配规则

###实现:

导入转换器基类

from werkzeug.routing import BaseConverter

自定义转换器

# 自定义正则转换器

class RegexConverter(BaseConverter):def __init__(self, url_map, *args):super(RegexConverter, self).__init__(url_map)# 将接受的第1个参数当作匹配规则进行保存self.regex = args[0]

添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re

app = Flask(__name__)
​
# 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: regex
app.url_map.converters['regex'] = RegexConverter

使用转换器去实现自定义匹配规则

当前此处定义的规则是:3位数字

@app.route('/index/<regex("[0-9]{3}"):id>')
def user_info(id):return "id 为 %s" % id

自定义转换器其他函数实现

继承于自定义转换器之后,还可以实现 to_python 和 to_url 这两个函数去对匹配参数做进一步处理:

to_python:

该函数参数中的 value 值代表匹配到的值,可输出进行查看

匹配完成之后,对匹配到的参数作最后一步处理再返回,比如:转成 int 类型的值再返回:

class RegexConverter(BaseConverter):def __init__(self, url_map, *args):super(RegexConverter, self).__init__(url_map)# 将接受的第1个参数当作匹配规则进行保存self.regex = args[0]
​def to_python(self, value):return int(value)

系统自带转换器

DEFAULT_CONVERTERS = {'default':          UnicodeConverter,'string':           UnicodeConverter,'any':              AnyConverter,'path':             PathConverter,'int':              IntegerConverter,'float':            FloatConverter,'uuid':             UUIDConverter,
}

6 增加日志记录、redis配置加载、mq配置加载
6.1 日志记录
Settings._init:

# 配置日志
# LOG_LEVEL = "DEBUG"
LOG_LEVEL = "INFO"

日志记录级别

FATAL/CRITICAL = 致命的,危险的
ERROR = 错误
WARNING = 警告
INFO = 信息
DEBUG = 调试
NOTSET = 没有设置

application._init:

1、日志模块基础配置,如:日志存放地址、日志记录格式、日志等级

#增加日志模块
def setup_log(Config):#设置日志等级logging.basicConfig(level=Config.LOG_LEVEL)# 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限file_log_handler=RotatingFileHandler('log/log',maxBytes=1024 * 1024 * 300, backupCount=10)# 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息formatter = logging.Formatter('%(asctime)s: %(levelname)s %(filename)s:%(lineno)d %(message)s')# 为刚创建的日志记录器设置日志记录格式file_log_handler.setFormatter(formatter)# 为全局的日志工具对象(flaskapp使用的)添加日志记录器logging.getLogger().addHandler(file_log_handler)

2、日志启动

#日志启动
setup_log(Config)

6.2 redis配置及加载
之前我们在config中已经把redis的配置已经写进去了,所以这里可以直接创redis连接池供app全局使用

application._init:

#新增redis连接模块
def connectRedis(Config):pool = redis.ConnectionPool(host=Config.REDIS_HOST, port=Config.REDIS_PORT, password=Config.REDIS_PASSWORD,max_connections=Config.REDIS_POLL)redis_store = redis.Redis(connection_pool=pool)return redis_store


使用示例:

@index_blu.route("/redis",methods=["POST","GET"])
def add_toRedis():logging.info("come to here")key = request.args.get("key")application.redis_store.set(key , "1233")value=application.redis_store.get( key )print(value)return "12333"


6.3 rabbitmq基础配置及加载

# rabbitmq配置访问
# 添加用户名和密码
credentials = pika.PlainCredentials(Config.RABBITUSER, Config.RABBITPASSWORD)
# 配置连接参数
parameters = pika.ConnectionParameters(host=Config.RABBITHOST, port=Config.RABBITPORT, credentials=credentials)
connection = pika.BlockingConnection(parameters)
channel = connection.channel()


使用示例:

@index_blu.route("/rabitmq",methods=["POST","GET"])
def add_rabitmq():logging.info("come to rabiitmq")application.channel.queue_declare(queue='queuetest2')
​return "33333"

7 全局拦截器配置
filerter.requestFilter

这里只是简单针对请求路径非index的进行拦截,如果还有其他拦截条件或者机制,可以继续在filter这个包下添加

from flask import request
import application
​
# 拦截器,每次的请求进来都会做的操作
@application.app.before_request
def before_action():# 获取当前请求的路由(路径)a = request.pathprint(a)u = a.split('/')if len(a)>2:if u[1] == 'index':print('success')else:return "无权限请求"


拦截器加载进app:

#拦截器加载
requestFilter.before_action


8 请求对象request和返回对象Response
请求对象request,使用前先导入request模块

from flask import request

获取url请求参数:request.args

获取form表单中的数据:request.form

获取请求体原始数据:request.data

获取文件数据:request.files

获取cookie:request.cookies

获取header信息:request.headers

获取请求方法:request.method

获取请求路径:request.path

Response

视图函数中可以返回的值

可以直接返回字符串,底层将这个字符串封装成了Response对象

元组,响应格式(响应体,状态码,头信息),不一定都要写,底层也是封装了一个Response对象

返回Response或其子类(jsonify子类返回标准json)

实现一个自定义Response对象步骤

继承Response对象

实现方法 force_typeforce_type(cls,rv,environ=None)

指定app.response为你定义的类

如果返回的值不是可以返回的对象,就会调用force_type方法

实现

class JSONResponse(Response):
​@classmethoddef force_type(cls, response, environ=None):'''这个方法只有视图函数返回非字符、非元祖、非Response对象才会调用:param response:是视图函数的返回值:param environ::return:'''print(response)print(type(response))if isinstance(response,(list,dict)):
​#jsonify除了将字典转换成json对象,还将对象包装成了一个Response对象response = jsonify(response)
​return super(JSONResponse,cls).force_type(response,environ) app.response_class = JSONResponse

9 异常捕获及自定义异常
捕获错误

errorhandler 装饰器

注册一个错误处理程序,当程序抛出指定错误状态码的时候,就会调用该装饰器所装饰的方法

参数:

code_or_exception – HTTP的错误状态码或指定异常

例如统一处理状态码为500,404的错误给用户友好的提示:

@app.errorhandler(500)
def internal_server_error(e):return '服务器搬家了哈哈哈'
​
@app.errorhandler(404)
def internal_server_error(e):return '瞎请求什么路径呢'


例如自定义错误413

@app.errorhandler(413)
def zero_division_error(e):return '除数不能为0'

异常捕获

abort 方法

抛出一个给定状态代码的 HTTPException 或者 指定响应,例如想要用一个页面未找到异常来终止请求,你可以调用 abort(404)。

参数:

code – HTTP的错误状态码

@index_blu.route("/exception",methods=["POST","GET"])
def exception():logging.info("come to exception")try:print(2)a=3/0except:abort(413)return "ooooo"

10 上下文 

上下文:即语境,语意,在程序中可以理解为在代码执行到某个时刻,根据之前代码锁做的操作以及下文即将要执行的逻辑,可以决定在当前时刻下可以使用到的变量,或者可以做的事情。

Flask中有两种上下文:请求上下文(request context)和应用上下文(application context)。

Flask中上下文对象:相当于一个容器,保存了Flask程序运行过程中的一些信息。

1.application指的是当你调用app = flask(name)创建的这个对象app。 2.request指的是每次http请求发生时,WSGI server(比如gunicorn)调用Flask.call()之后,在Flask对象内部创建的Request对象; 3.application表示用于相应WSGI请求的应用本身,request表示没出http请求; 4.appliacation的生命周期大于request,一个application存活期间,可能发生多次http请求,所以,也就会有多个request;

请求上下文(request context):在Flask中,可以直接在视图函数中使用request这个独享进行获取先关数据,而request就是请求上下文的对象,保存了当前本次请求的相关数据,请求上线文对象有:request、session

request:封装了HTTP请求的内容,针对的是http请求。例如:user = request.args.get('user'),获取的是get请求的参数。

session:用来记录请求会话中的信息,针对的是用户信息。例如:session['name'] = user.id 科可以记录用户信息。还可以通过session.get('name')获取用户信息。

应用上下文(application context):它不是一直存在的,它只是request context中的一个对app的代理,所谓的local proxy。它的作用主要是帮助request获取当前的应用,它是伴request而生,随request而灭的。

应用上下文对象有:current_app,g

current_app:应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量,例如:

应用的启动脚本是哪个文件,启动时指定了哪些参数

加载了哪些配置文件,导入了哪些配置

连接了哪个数据库

有哪些可以调用的工具类、常量

当前flask应用在哪个机器上,哪个IP上运行,内存多大

current_app.name
current_app.test_value='value'

g变量:g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别

g.name='abc'
注意:不同的请求,会有不同的全局变量

两者的区别:

请求上下文:保存了客户端和服务器交互的数据

应用上下文:flask 应用程序运行过程中,保存的一些配置信息,比如程序名、数据库连接、应用信息等

11 部署
gunicorn作为服务器,安装gunicorn

pip3 install gunicorn

启动

gunicorn -w 3 -b 127.0.0.1:8000 app:app

-w 处理进程数

-b 运⾏主机ip端⼝

dpj.wsgi 项⽬的wsgi

gunicorn常⽤配置

-c CONFIG : CONFIG,配置⽂件的路径,通过配置⽂件启动;⽣产环境使⽤; 
​
-b ADDRESS : ADDRESS,ip加端⼝,绑定运⾏的主机; 
​
-w INT, --workers INT:⽤于处理⼯作进程的数量,为正整数,默认为1; 
​
-k STRTING, --worker-class STRTING:要使⽤的⼯作模式,默认为sync异步,可以下载 
​
eventlet和gevent并指定 
​
--threads INT:处理请求的⼯作线程数,使⽤指定数量的线程运⾏每个worker。为正整数,默认为1。 
​
--worker-connections INT:最⼤客户端并发数量,默认情况下这个值为1000。 
​
--backlog int:未决连接的最⼤数量,即等待服务的客户的数量。默认2048个,⼀般不修改; 
​
-p FILE, --pid FILE:设置pid⽂件的⽂件名,如果不设置将不会创建pid⽂件 
​
--access-logfile FILE : 要写⼊的访问⽇志⽬录--access-logformat STRING:要写⼊的访问⽇志格式 
​
--error-logfile FILE, --log-file FILE : 要写⼊错误⽇志的⽂件⽬录。 
​
--log-level LEVEL : 错误⽇志输出等级。 
​
--limit-request-line INT : HTTP请求头的⾏数的最⼤⼤⼩,此参数⽤于限制HTTP请求⾏的允 
​
许⼤⼩,默认情况下,这个值为4094。值是0~8190的数字。 
​
--limit-request-fields INT : 限制HTTP请求中请求头字段的数量。此字段⽤于限制请求头字 
​
段的数量以防⽌DDOS攻击,默认情况下,这个值为100,这个值不能超过32768 
​
--limit-request-field-size INT : 限制HTTP请求中请求头的⼤⼩,默认情况下这个值为8190 
​
字节。值是⼀个整数或者0,当该值为0时,表示将对请求头⼤⼩不做限制 
​
-t INT, --timeout INT:超过这么多秒后⼯作将被杀掉,并重新启动。⼀般设定为30秒; 
​
--daemon: 是否以守护进程启动,默认false; 
​
--chdir: 在加载应⽤程序之前切换⽬录; 
​
--graceful-timeout INT:默认情况下,这个值为30,在超时(从接收到重启信号开始)之后仍然活着 
​
的⼯作将被强⾏杀死;⼀般使⽤默认; 
​
--keep-alive INT:在keep-alive连接上等待请求的秒数,默认情况下值为2。⼀般设定在1~5秒之 
​
间。 
​
--reload:默认为False。此设置⽤于开发,每当应⽤程序发⽣更改时,都会导致⼯作重新启动。 
​
--spew:打印服务器执⾏过的每⼀条语句,默认False。此选择为原⼦性的,即要么全部打印,要么全部 
​
不打印; 
​
--check-config :显示现在的配置,默认值为False,即显示。 
​
-e ENV, --env ENV: 设置环境变量;

本次分享到此结束,觉得有所帮助的朋友点点关注点点赞!

相关文章:

Flask项目搭建及部署 —— Python

flask搭建及部署 pip 19.2.3 python 3.7.5 Flask 1.1.1 Flask-SQLAlchemy 2.4.1 Pika 1.1.0 Redis 3.3.11 flask-wtf 0.14.2 1、创建flask项目&#xff1a; 创建完成后整个项目结构树&#xff1a; app.py: 项⽬管理⽂件&#xff0c;通过它管理项⽬。 static: 存放静态…...

【C++报错已解决】Invalid Use of ‘this’ Pointer

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言 一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;修正‘this’指针使用2…...

群晖NAS配置WebDav服务结合内网穿透实现跨平台云同步思源笔记

文章目录 前言1. 开启群晖WebDav 服务2. 本地局域网IP同步测试3. 群晖安装Cpolar4. 配置远程同步地址5. 笔记远程同步测试6. 固定公网地址7. 配置固定远程同步地址 前言 本教程主要分享如何将思源笔记、cpolar内网穿透和群晖WebDav三者相结合&#xff0c;实现思源笔记的云同步…...

内容监管与自由表达:Facebook的平衡之道

在当今数字化信息社会中&#xff0c;社交媒体平台不仅是人们交流和获取信息的主要渠道&#xff0c;也是自由表达的重要舞台。Facebook&#xff0c;作为全球最大的社交网络平台&#xff0c;连接了数十亿用户&#xff0c;形成了一个丰富多样的信息生态。然而&#xff0c;如何在维…...

电脑桌面日历记事本怎么弄 好用的桌面日历记事本

在这个数字化的时代&#xff0c;电脑已成为我们日常生活中不可或缺的伙伴。我常常在电脑上记录各种事项&#xff0c;以便随时查看和提醒自己。而我最钟爱的记事方式&#xff0c;莫过于使用桌面日历记事本。 想象一下&#xff0c;你的电脑桌面上有一个直观的日历&#xff0c;每…...

#招聘数据分析#2024年6月前程无忧招聘北上广深成渝对比情况

#招聘数据分析#2024年6月前程无忧招聘北上广深成渝对比情况 0、根据前程无忧不完全样本统计&#xff0c;北上广深成都重庆平均月工资从高到低依次为 北京15441元、上海14425元、深圳13310元、广州11192元、成都10539元、重庆10290。 1、成都招聘样本数全量35228个&#xff0c…...

STM32 IIC详解(软件模拟)

目录 一、IIC协议基本原理 1.IIC协议概述 2.时序图分析 二、代码分析 1.IIC初始化 2.IIC起始信号 3.IIC发送数据 4.获取应答信号 5.读一个字节 6.产生ACK应答 7.不产生ACK应答 IIC&#xff08;Inter-Integrated Circuit&#xff09;在嵌入式系统中是一种常见的数据通…...

推三返一小程序商城开发搭建

推三返一小程序商城开发主要涉及到以下几个步骤&#xff1a; 确定需求和功能&#xff1a; 首先需要明确小程序商城的开发需求和功能。商家需要思考自己想要实现什么功能&#xff0c;例如推广、销售、裂变等。 同时还需要考虑小程序的页面设计、用户体验等方面。 选择合适的开…...

项目机会:4万平:智能仓,AGV,穿梭车,AMR,WMS,提升机,机器人……

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 如下为近期国内智能仓储物流相关项目的公开信息线索&#xff0c;这些项目具体信息会发布到知识星球&#xff0c;请感兴趣的球友先人一步到知识星球【智能仓储物流技术研习社】自行下载…...

[工具类]Java 合并、拆分PPT幻灯片

本文将介绍在Java程序中如何来合并及拆分PPT文档的方法。示例大纲&#xff1a; 1. 合并 1.1 将指定幻灯片合并到文档 1.2 合并多个幻灯片文档为一个文档 2. 拆分 2.1 按幻灯片每一页单独拆分为一个文档 2.2 按指定幻灯片页数范围来拆分为多个文档 使用工具&#xff1a;F…...

深入了解 Timber:全面掌握 Android 日志记录的最佳实践

深入了解 Timber&#xff1a;全面掌握 Android 日志记录的最佳实践 Timber 是由 Jake Wharton 提供的一个流行的 Android 日志记录库。它旨在简化日志记录、增强日志管理&#xff0c;并提高代码的可维护性。在本文中&#xff0c;我们将深入探讨 Timber 的功能、使用方法以及最…...

阿一课代表随堂分享:红队反向代理之使用frp搭建反向代理

frp反向代理 frp简介 frp 是一个开源、简洁易用、高性能的内网穿透和反向代理软件&#xff0c;支持 tcp, udp, http, https等协议。 frp 是一个可用于内网穿透的高性能的反向代理应用&#xff0c;分为服务端frps和客户端frpc&#xff0c;支持 tcp, udp, http, https 协议。详…...

基于vue的引入登录界面

以下是一些常见的登录页面布局&#xff1a; 1. 中心布局 - 登录表单位于页面的中心位置&#xff0c;通常包括用户名输入框、密码输入框、登录按钮等元素。页面背景简洁&#xff0c;以突出登录表单。 - 这种布局常见于大多数网站和应用&#xff0c;简洁明了&#xff0c;用户注意…...

centos7升级到欧拉openeule

centos7升级到欧拉openeule 一、准备工作 1、安装迁移工具&#xff08;安装迁移工具的机器不能给自己升级&#xff0c;请用其他机器作为迁移母机&#xff09; wget https://repo.oepkgs.net/openEuler/rpm/openEuler-20.03-LTS-SP1/contrib/x2openEuler/x86_64/Packages/x2…...

阿里云 Ubuntu 开启允许 ssh 密码方式登录

以前用的 centos&#xff0c;重置系统为 ubuntu 后在ssh 远程连接时遇到了点问题&#xff1a; 在阿里云控制台重置实例密码后无法使用密码进行 SSH 连接登录 原因&#xff1a;阿里云 Ubuntu 默认禁用密码登录方式 解决办法&#xff1a; 先使用其他用户登录到服务器 这里进来…...

利用投标相似度辅助围串标判定

摘要 围标&#xff08;bid rigging&#xff09;是一种非法的竞争行为&#xff0c;对市场公平性和公共资源分配造成严重影响。本文探讨了如何利用投标相似度来辅助判定围标行为。通过详细分析投标文件的内容相似性&#xff0c;选取适当的指标进行相似度计算&#xff0c;并结合实…...

iOS 开发者的 Flutter 入门课

作为一名 iOS 开发者&#xff0c;入门 Flutter 需要了解一些新的工具和概念&#xff0c;但也能利用你已有的知识和技能。以下是一个详细的入门指南&#xff0c;帮助你快速上手 Flutter&#xff1a; 1. 环境设置 首先&#xff0c;你需要设置开发环境。 安装 Flutter SDK 前往…...

单机版k8s搭建

环境配置&#xff1a; 关闭防火墙和交换内存 systemctl stop ufwsudo swapoff -a安装Docker 更新安装包 sudo apt-get update安装依赖 sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates获取证书 curl -fsSL http://mirrors.a…...

IDEA创建Spring项目无法使用Java8的解决方案

文章目录 一&#xff0c;创建Project&#xff0c;无法选择Java81&#xff0c;无法选择Java82&#xff0c;选择JDK17报错 二&#xff0c;原因分析1&#xff0c;Spring Boot将来会全力支持Java17&#xff0c;不再维护支持Java8的版本 三&#xff0c;解决方案1&#xff0c;使用国内…...

无障碍快捷方式图标

问题背景 测试反馈&#xff0c;无障碍快捷方式和setting里的无障碍图标不一致。 无障碍快捷方式悬浮窗 1、悬浮窗在systemui中 frameworks\base\packages\SystemUI\src\com\android\systemui\accessibility\floatingmenu\AccessibilityTargetAdapter.java 图标获取方式&…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

云原生周刊:k0s 成为 CNCF 沙箱项目

开源项目推荐 HAMi HAMi&#xff08;原名 k8s‑vGPU‑scheduler&#xff09;是一款 CNCF Sandbox 级别的开源 K8s 中间件&#xff0c;通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度&#xff0c;为容器提供统一接口&#xff0c;实现细粒度资源配额…...