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

做g3云推广需要网站/网络营销推广计划书

做g3云推广需要网站,网络营销推广计划书,全屋定制十大品牌,网站营销方法启动新项目时需要做出的决定之一是使用哪个数据库。如果您使用的是Django这样的包含电池的框架,那么没有理由再三考虑。选择一个受支持的数据库引擎,就可以了。另一方面,如果你使用像FastAPI或Flask这样的微框架,你需要自己做出这…

启动新项目时需要做出的决定之一是使用哪个数据库。如果您使用的是Django这样的包含电池的框架,那么没有理由再三考虑。选择一个受支持的数据库引擎,就可以了。另一方面,如果你使用像FastAPI或Flask这样的微框架,你需要自己做出这个决定。您的决策会影响您需要哪些库以及如何进行数据建模。虽然你可能只是接触Postgres,但还有其他选择。其中之一是DynamoDB。与Postgres一样,它也是Python项目的绝佳选择。

在本文中,我将比较Postgres和DynamoDB。我将描述如何使用它们,解释它们的区别,并帮助您决定为Python应用程序选择哪一个。

什么是Postgres?什么是DynamoDB

Postgres是一个关系数据库管理系统(RDBMS)。这是一个开源项目,已经存在了35年多。它是一个成熟稳定的数据库引擎。对于大多数项目来说,这是一个不错的选择。

DynamoDB是AWS提供的NoSQL数据库服务。这是一项完全管理的服务,这意味着您不需要担心扩展、备份或可用性。对于需要快速扩展并且不想花时间管理数据库的项目来说,这是一个很好的选择。

第一个明显的区别是Postgres是SQL数据库,而DynamoDB是NoSQL数据库。这并不能告诉我们什么。是的,DynamoDB不是SQL数据库,但它是什么?DynamoDB实际上是一个键/值数据库。这对你的申请意味着什么?我们怎么能比较这两个数据库呢?密钥/值存储真的不就是Redis吗?我们现在还不要妄下结论。让我们先来看一个例子。

比如说我们需要管理TODO任务。一种经典的SQL方法是创建这样一个表:
在这里插入图片描述
然后我们可以查询它以获取给定所有者的所有任务:

SELECT * FROM tasks WHERE owner = ' john@doe.com';

DynamoDB的情况有所不同。DynamoDB是一个密钥/值存储。我们可以在两个关键模式之间进行选择。我们只能使用HASH密钥。在这种情况下,我们需要知道ID才能查询记录(可以将其视为Redis)。使用这个密钥模式,我们会有一个这样的表:
在这里插入图片描述
我们可以查询它以获取给定ID的任务:

import boto3dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("tasks")table.get_item(Key={"ID": "some_id",},
)

因此,没有办法有效地列出给定所有者的任务。

实际上,您可以使用扫描来扫描整个表,但这是非常低效的,应该避免。

幸运的是,还有另一个选项,HASH&RANGE密钥模式。在这种情况下,我们可以使用两个键来识别一个记录。我们可以使用HASH键来标识分区,使用RANGE键来标识该分区内的记录。HASH和RANGE键组合对于每个记录都必须是唯一的。在我们的情况下,我们可以将owner用作HASH密钥,将ID用作RANGE密钥。在这种情况下,我们会有这样的表格:
在这里插入图片描述
有了这样的结构,我们可以查询给定所有者的所有任务,如下所示:

import boto3
from boto3.dynamodb.conditions import Keydynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("tasks")table.query(KeyConditionExpression=Key("Owner").eq("john@doe.com"),
)

现在,您将获得所有者为 john@doe.com 的所有记录,这些记录将按ID排序。
尽管我们只是触及了表面,但我想指出一点:您可以使用Postgres或DynamoDB作为您的应用程序数据库。您只需要以不同的方式处理数据建模。

ORMs

ORM(对象关系映射器)是允许您轻松地将数据库记录映射到Python对象的库。它们大多遵循活动记录或数据映射器模式。使用活动记录模式,模型对象负责业务逻辑和数据持久性。Django ORM就是这样一个例子。对于数据映射器,这两个职责被委派给两个对象,模型对象包含属性和业务逻辑,而映射器对象负责数据持久性。一个例子是SQLAlchemy。它们构建在SQL数据库之上。因此,Postgres有很多ORM选项可供选择也就不足为奇了——SQLAlchemy、Django ORM、Peewee、PonyORM等等。

选择哪一个主要取决于个人喜好。虽然语法可能不同,但它们都允许您轻松定义模型和查询数据库。让我们来看看使用SQLAlchemy的示例:

from  sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmakerBase = declarative_base()class Task(Base):__tablename__ = "tasks"id = Column(Integer, primary_key=True, autoincrement=True)title = Column(String)status = Column(String)owner = Column(String)engine = create_engine("postgresql://postgres:postgres@localhost:5432/postgres")
Base.metadata.create_all(engine)Session = sessionmaker(bind=engine)
session = Session()task = Task(title="Clean your office", status="OPEN", owner="john@doe.com")
session.add(task)
session.commit()tasks = session.query(Task).filter(Task.owner == "john@doe.com").all()
print(tasks)

正如您所看到的,这非常简单:定义模型,创建会话,然后查询数据库。您可以对其他ORM使用相同/相似的方法。

虽然在Postgres中使用ORM时情况会非常好,但我不能对DynamoDB说同样的话。DynamoDB有一些ORM,例如PynamoDB和DynamORM,但在我看来,它们破坏了DynamoDB的整个目的。如果你想真正从DynamoDB中受益,你应该采用单表设计——ORM不支持这种设计。我所说的“真正的好处”是指实际使用DynamoDB,而不是在其上构建另一个带有UUID的关系数据库。让我们来看看如何使用它。

等效于NoSQL数据库的ORM是ODM(对象文档映射器)。例如,请参阅MongoDB的ODM。与ORM一样,它们简化了与数据库的交互。您也可以为DynamoDB找到类似的解决方案,例如,DynamoDB mapper。深入了解后,您会意识到它们没有得到广泛使用,没有得到维护,没有做好生产准备,或者它们强制执行了不必要的约束。

在这里插入图片描述
您可以看到以下内容:

  • HASH键有一个通用名称 PK (分区键)。它可以用于不同类型的记录。
  • RANGE键有一个通用名称 SK (排序键)。它可以用于不同类型的记录。

我们保留了其余的内容,所以我们可以很容易地将数据映射回模型对象。由于DynamoDB是无模式的,所以我们只需要为每个记录提供PK和SK。其他一切都是可选的。这使我们能够对不同类型的记录使用一个表。

为了支持更复杂的示例(和查询),需要对PK和SK使用复合密钥。例如,任务和板的密钥结构不同:
Tasks: PK=#TASK#{owner}, SK=#TASK#{task_id}.
Boards: PK=#BOARD#{owner}, SK=#BOARD#{contact_id}.
这使您能够按所有者轻松查询所有任务或按所有者查询所有板。ORM不鼓励使用单表设计所必需的复合键。这也是ORM在DynamoDB中表现不佳的原因之一。你可以阅读这篇有趣的文章来了解更多。

DynamoDB注重可预测的性能。这就是为什么我们只能通过HASH和RANGE键查询记录(HASH键必须始终存在于查询中)。

无法按其他列进行查询;您可以使用索引来支持更多的查询,但稍后会详细介绍。

因此,我们必须围绕查询而不是数据构建数据模型。这也适用于建立关系模型。使用ORM,您只需定义两个模型之间的外键关系。然后,您将能够通过其父对象访问相关对象,反之亦然。没有必要做任何其他事情。虽然这对于简单的应用程序来说可能很方便,但它可能会成为应用程序中的一个巨大瓶颈(N+1查询)。使用DynamoDB单表设计,希望通过一个查询加载所需的所有内容。

例如,如果你想加载一个包含所有任务的板,你必须对DynamoDB进行单个查询。它将返回不同类型的记录:板(名称、上次更新…)、打开的任务、关闭的任务等等。然后,由您将这些内容映射到包含任务等的板对象。因此,几乎不可能为DynamoDB构建通用ORM。所有内容都非常特定于用例/查询。虽然这听起来像是一项艰巨的工作,但它迫使你进行高效的设计。因此,使用DynamoDB,您需要为数据持久性构建自己的抽象——例如,存储库。您可以指定您的纯Python(或pydantic或其他)模型,并使用Boto3来实现您的存储库。

Models:

from  dataclasses import dataclass
from enum import Enum
from uuid import UUIDclass TaskStatus(str, Enum):OPEN = "OPEN"CLOSED = "CLOSED"@dataclass
class Task:id: UUIDtitle: strstatus: TaskStatusowner: str@classmethoddef create(cls, id_, title, owner):return cls(id_, title, TaskStatus.OPEN, owner)

Store:

from uuid import UUID  import boto3
from boto3.dynamodb.conditions import Keyfrom models import Task, TaskStatusclass TaskStore:def __init__(self, table_name):self.table_name = table_namedef add(self, task):dynamodb = boto3.resource("dynamodb")table = dynamodb.Table(self.table_name)table.put_item(Item={"PK": f"#TASK#{task.owner}","SK": f"#TASK#{task.id}","id": str(task.id),"title": task.title,"status": task.status.value,"owner": task.owner,})def list_by_owner(self, owner):dynamodb = boto3.resource("dynamodb")table = dynamodb.Table(self.table_name)last_key = Nonequery_kwargs = {"IndexName": "GS1","KeyConditionExpression": Key("PK").eq(f"#TASK#{owner}"),}tasks = []while True:if last_key is not None:query_kwargs["ExclusiveStartKey"] = last_keyresponse = table.query(**query_kwargs)tasks.extend([Task(id=UUID(record["id"]),title=record["title"],owner=record["owner"],status=TaskStatus[record["status"]],)for record in response["Items"]])last_key = response.get("LastEvaluatedKey")if last_key is None:breakreturn tasks

简而言之,Postgres和DynamoDB都有ORM。您可能想在Postgres中使用一个,但可能不想在DynamoDB中使用。

Migrations

另一个有趣的主题–数据库迁移。数据库迁移提供了一种更新数据库模式的方法。对于Postgres,有一些工具可以简化迁移

  • Alembic
  • Django migrations

您可以使用它们轻松地将表/索引/列/约束添加到数据库中。它们甚至可以通过ORM从模型定义中自动生成。Alembic迁移示例:

"""create tasks tableRevision ID: 1f8b5f5d1f5a
Revises:
Create Date: 2021-12-05 12:00:00.000000"""from   alembic import op
import sqlalchemy as sa# revision identifiers, used by Alembic.
revision = "1f8b5f5d1f5a"
down_revision = None
branch_labels = None
depends_on = Nonedef upgrade():op.create_table("tasks",sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),sa.Column("title", sa.String),sa.Column("status", sa.String),sa.Column("owner", sa.String),)def downgrade():op.drop_table("tasks")

对于大多数常见的操作,它非常简单。对于自动生成的迁移,没有太多工作要做。如果需要,您可以随时手动编写。

对于DynamoDB,没有模式——我们也说过我们想要一个表。无法更改密钥,因此无法迁移。还是有?事实证明,在向记录添加/从记录中删除属性时,您有两个选项:

  1. 在运行时处理更改–例如,添加具有默认值的列
  2. 遵循以下三步模式:
    1 开始使用新的“属性”写入新记录
    2 使用新的“属性”将现有记录更新为所需值(您可以扫描表中的所有记录并更新它们)
    3 开始在代码中使用新的“属性”

您可以将三步模式推广到其他类型的更改,如删除属性。
有了所有可用的工具,Postgres的迁移更容易。

如果您在更复杂的项目中工作,而性能差或停机时间确实不是一种选择,那么您可能会手动编写大部分迁移代码。对于这种情况,Postgres和DynamoDB之间没有太大的区别。

Queries

事实上,我们已经谈到了这个话题。我们甚至查看了示例查询。尽管如此,让我们更深入地挖掘。

任何不习惯DynamoDB的人都会说,由于查询数据的能力非常有限,使用它没有意义。的确,查询在DynamoDB中的灵活性要低得多。人们普遍认为,在使用SQL数据库时,可以使用所需的任意列集查询任何数据。理论上是这样的。换句话说,只有当您的数据库足够小,可以放入服务器的内存时,这才是正确的。

一旦您有了更严重的数据量,查询往往会变慢,这反过来又会减慢应用程序的速度。迟早,你需要开始考虑指数。要进行快速查询,您需要添加索引并仅按索引列进行查询。您还将意识到,如果不限制返回记录的数量,您将无法进行查询。无限制的查询很容易导致系统瘫痪。这是因为你根本不知道他们会返回多少数据。您的数据库可能需要从磁盘读取10亿行,这需要时间。

那我们该何去何从呢?DynamoDB的构建方式迫使您提前考虑这些问题。

在设计数据模型时,您需要:

  1. 使用HASH键对数据进行分区
  2. 使用RANGE键对数据进行排序

然后,您只能通过HASH和RANGE键或预定义的索引进行查询,这些索引有自己的HASH和RANGE键。单个查询返回的数据量也有限制。所以你不得不使用分页。

所有这些限制在一开始可能听起来很可怕,让人不知所措。一旦你习惯了它们,你就会意识到它们的存在是有原因的。让我们来看看示例查询。。。

With DynamoDB:

import boto3
from boto3.dynamodb.conditions import Keyowner = "john@doe.com"dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("tasks-api")
last_key = None
query_kwargs = {"IndexName": "GS1","KeyConditionExpression": Key("PK").eq(f"#TASK#{owner}"),
}
tasks = []while True:if last_key is not None:query_kwargs["ExclusiveStartKey"] = last_keyresponse = table.query(**query_kwargs)tasks.extend(response["Items"])last_key = response.get("LastEvaluatedKey")if last_key is None:breakprint(tasks)

使用Postgres+SQLAlchemy(分页查询):

from   models import Session, Tasktasks = []
last_evaluated_id = -1
session = Session()while True:query = session.query(Task).filter(Task.id > last_evaluated_id).order_by(Task.id).limit(10)tasks.extend(query.all())last_evaluated_id = tasks[-1].idif len(tasks) < 10:breakprint(tasks)

正如您所看到的,DynamoDB和Postgres分页查询在代码复杂度上没有太大区别。

DynamoDB还有其他查询限制:

  1. 我们必须始终至少提供HASH密钥
  2. 我们只能通过HASH和RANGE键或预定义索引进行查询
  3. 返回的记录按RANGE键排序。您只能在升序和降序之间进行选择

我们知道,在当前的表设计中,我们只能支持两个查询:

  1. 按所有者列出(您已在上面看到)
  2. 按所有者和任务ID获取(您可以在下面看到)
import boto3
from boto3.dynamodb.conditions import Keyowner = "john@doe.com"
task_id = "7b0f4bc8-4751-41f1-b3b1-23a935d81cd6"dynamodb = boto3.resource("dynamodb", endpoint_url="http://localhost:9999")
table = dynamodb.Table("tasks-api")query_kwargs = {"KeyConditionExpression": Key("PK").eq(f"#TASK#{owner}") & Key("SK").eq(f"#TASK#{task_id}"),
}
task = response = table.query(**query_kwargs)["Items"][0] print(task)

例如,我们不能按状态进行查询。但我们可以用Postgres做到这一点:

from models import Session, Tasktasks = []
last_evaluated_id = -1
session = Session()while True:query = session.query(Task).filter(Task.status == "OPEN").filter(Task.id > last_evaluated_id).order_by(Task.id).limit(10)tasks.extend(query.all())last_evaluated_id = tasks[-1].idif len(tasks) < 10:breakprint(tasks)

别担心,我们仍然可以在DynamoDB中支持这样的查询。我们只需要添加即可使用全局二级索引(GSI)。我们可以创建一个名为GS1的具有单个GSI的表,如下所示:

import boto3client = boto3.client("dynamodb", endpoint_url="http://localhost:9999")
client.create_table(TableName="tasks-api",KeySchema=[{"AttributeName": "PK", "KeyType": "HASH"},{"AttributeName": "SK", "KeyType": "RANGE"},],AttributeDefinitions=[{"AttributeName": "PK", "AttributeType": "S"},{"AttributeName": "SK", "AttributeType": "S"},{"AttributeName": "GS1PK", "AttributeType": "S"},{"AttributeName": "GS1SK", "AttributeType": "S"},],GlobalSecondaryIndexes=[{"IndexName": "GS1","KeySchema": [{"AttributeName": "GS1PK", "KeyType": "HASH"},{"AttributeName": "GS1SK", "KeyType": "RANGE"},],"Projection": {"ProjectionType": "ALL"},},],BillingMode="PAY_PER_REQUEST",
)

就像表格一样,GSI有自己的HASH和RANGE键。然后,我们可以按如下状态进行查询:

import boto3
from boto3.dynamodb.conditions import Keystatus = "OPEN"dynamodb = boto3.resource("dynamodb", endpoint_url="http://localhost:9999")
table = dynamodb.Table("tasks-api")
last_key = None
query_kwargs = {"KeyConditionExpression": Key("GS1PK").eq(f"#TASK#{status}"),"IndexName": "GS1",
}
tasks = []while True:if last_key is not None:query_kwargs["ExclusiveStartKey"] = last_keyresponse = table.query(**query_kwargs)tasks.extend(response["Items"])last_key = response.get("LastEvaluatedKey")if last_key is None:breakprint(tasks)

正如您所看到的,您需要显式定义查询时要使用的索引。另一方面,Postgres自己做到了这一点。再一次,如果您比较查询,您会发现它们毕竟没有那么大的不同。

只要您使用的是精确的查询(=,!=,>,<,…),Postgres和DynamoDB之间就没有太大区别。使用DynamoDB,您无法进行LIKE、IN等查询或全文搜索。要支持这样的功能,您需要将其与Elasticsearch或类似功能配对。

您可以在此处看到HASH/RANGE键支持的条件的完整列表。

简而言之,当用作应用程序数据库时,这两个数据库都应该支持您的需求。如果你想进行更复杂的查询(例如,报告、分析等),你要么需要使用Postgres,要么将DynamoDB与其他一些服务配对,如Elasticsearch、Athena或Redshift等。

Performance

性能总是一个棘手的话题。进入“意见”领域是很容易的。我会尽量避免的。如果你在网上搜索,你会发现有人赞扬DynamoDB,诋毁Postgres,反之亦然。事实是,在大多数情况下,你会看到以下缺陷之一:

  1. DynamoDB被用作关系数据库——多个表,没有单表设计
  2. Postgres的索引/分区很差
  3. 扫描与DynamoDB一起使用
  4. Postgres被非索引列或无限制查询

这些年来,我在各种生产环境中都使用过这两种方法。我可以告诉你以下几点:如果使用得当,它们都会燃烧得很快。当直接比较时,您可能会注意到它们之间的细微差异,但从应用程序的角度来看,您不会注意到太大的性能差异。当然,在亚马逊/谷歌/奈飞等网站。规模,你会明显地看到一些不同;毕竟,创建DynamoDB是有原因的。

长话短说:对于大多数项目来说,性能不应该是主要的决定因素。至少如果你不是亚马逊/网飞/。。。。相反,把时间花在开发一个高效的数据(访问)模型上,你会没事的。

Backups

备份是一个经常被遗忘的主题。没有备份之前一切都很好。由于我们已经在AWS和DynamoDB中,让我们将AWS RDS上的Postgres与DynamoDB进行比较。

它们都支持按需备份和连续备份。它们都提供时间点恢复,我强烈建议您这样做。我强烈建议您同时使用内置备份。对于时间点恢复,两者的流程基本相同:

  1. 从给定的时间戳创建一个时间点恢复,这将创建一个新实例(RDS)或一个新表(DynamoDB)
  2. 将已恢复数据中丢失的数据复制到应用程序实例/表,或将应用程序重新路由到新实例/表

提示:AWS上的备份符合SOC 2等证书。

您可以从DynamoDB和RDS的官方文档中了解更多信息。

Transactions

在我们结束之前,让我们谈一谈事务。事务是一种允许我们将多个操作封装到单个数据库操作中的机制。这有助于确保要么执行所有操作,要么不执行任何操作。例如,通过这种方式,我们可以确保减少库存项目的数量并创建新订单。如果没有交易,我们可能会收到一个没有库存的订单——例如,有人在你之前下了订单。

事务是SQL数据库的“面包和黄油”。另一方面,它们在NoSQL数据库中并不常见。Postgres和DynamoDB都支持事务——要么全部支持,要么什么都不支持。它们在Postgres中可能感觉更惯用,但您也可以在DynamoDB中使用它们。您只需要使用较低级别的Boto3 API。

因此,在这方面,您应该可以使用DynamoDB或Postgres。

您可以从DynamoDB和Postgres的官方文档中了解更多信息。

我应该使用哪一个

所有这些都给你留下了一个问题:我应该使用哪一个?对于大多数情况,您可以使用其中任何一种。尽管如此,还是有一些指导原则可以帮助您进行选择:

  1. 如果您正在使用Django(或任何其他包含电池的框架),请使用Postgres。这是最简单的方法。如果您尝试使用DynamoDB,那么您只需要与框架作斗争。
  2. 如果你有一个缺乏经验的团队,去Postgres。这更容易让你的头脑清醒起来,并在以后纠正你的错误。
  3. 如果您需要在多个AWS区域轻松复制数据,请使用DynamoDB。它就是为这个而建的。
  4. 如果您的流量非常大,请选择DynamoDB。您可以按要求付款。
  5. 如果你想无服务器化,那就选择DynamoDB。但在这种情况下,您也需要在Lambda上运行您的应用程序。
  6. 如果您不在AWS生态系统中,请使用Postgres。DynamoDB与AWS紧密相连。

无论您选择哪种,请记住,拥有一个高效的数据模型比您使用的数据库更重要。DynamoDB会强迫你这么做。Postgres不会。但正如您所看到的,当有效地使用它们时,您最终会得到非常相似的使用模式。

结论

虽然本文涵盖了很多内容,但仍有很多内容需要探索。那么接下来该怎么办呢?你可以用它们两个构建同一个应用程序,以真正掌握它们。我们——惊喜,惊喜!——有两门课程可以帮助你做到这一点:

  1. Serverless FastAPI course
  2. Scalable FastAPI course

前者使用DynamoDB,后者使用Postgres。试着用两者构建相同的东西,你会看到它的进展。如果没有别的,我相信一旦完成,你在数据建模方面会做得更好。

您还可以使用本文中的示例:GitHub repository。

相关文章:

Postgres与DynamoDB:选择哪个数据库

启动新项目时需要做出的决定之一是使用哪个数据库。如果您使用的是Django这样的包含电池的框架&#xff0c;那么没有理由再三考虑。选择一个受支持的数据库引擎&#xff0c;就可以了。另一方面&#xff0c;如果你使用像FastAPI或Flask这样的微框架&#xff0c;你需要自己做出这…...

【ELK】logstash快速入门

1.概述 1.1.什么是logstash&#xff1f; 之前我们聊了es&#xff0c;并且用docker搭建了一个eskibana的环境。es目前最普遍的用法是用来存储日志的&#xff0c;然后结合kibana对日志做一些可视化的工作。既然要收集日志&#xff0c;就面临着一个问题&#xff1a; 各个系统的…...

SQL sever2008中创建用户并赋权

一、创建数据库dream CREATE DATABASE dream; 二、创建登录用户XZS 法一&#xff1a;使用SSMS创建 通过查询 sys.syslogins 系统视图来确定当前登录是否具有系统管理员权限。执行以下查询语句&#xff1a; SELECT name, isntname FROM sys.syslogins WHERE sysadmin 1;选…...

SpringBoot2-Jwt

1.官网 jwt.io/libraries 2.选jose4j pom <dependency><groupId>org.bitbucket.b_c</groupId><artifactId>jose4j</artifactId><version>0.9.4</version> </dependency> 3.创建jwt工具 public class JwtUtil {private stat…...

2、安全开发-Python-Socket编程端口探针域名爆破反弹Shell编码免杀

用途&#xff1a;个人学习笔记&#xff0c;欢迎指正&#xff01; 目录 主要内容&#xff1a; 一、端口扫描(未开防火墙情况) 1、Python关键代码: 2、完整代码&#xff1a;多线程配合Queue进行全端口扫描 二、子域名扫描 三、客户端&#xff0c;服务端Socket编程通信cmd命…...

Python 套接字详解:与网络通信的温柔邂逅

网络世界&#xff0c;犹如一片无垠的海洋&#xff0c;充满了无限的可能性和无尽的探索。而在这个浩瀚的网络宇宙中&#xff0c;Python 语言以其简洁优雅、功能丰富而备受青睐。在 Python 的世界里&#xff0c;有一个神奇的工具&#xff0c;它就像是一座桥梁&#xff0c;将不同的…...

如何在Linux系统中安装MySQL

要在Linux系统中安装MySQL&#xff0c;您可以使用系统的包管理工具。以下是一些常见的Linux发行版的安装命令&#xff1a; 1. **Ubuntu/Debian:** bash sudo apt-get update sudo apt-get install mysql-server 2. **Fedora:** bash sudo dnf install mysql-server 3. **Cent…...

51单片机基础:定时器

1.定时器介绍 51单片机通常有两个定时器&#xff1a;定时器 0/1&#xff0c;好一点的可能有定时器3。 在介绍定时器之前我们先科普下几个知识&#xff1a; 1&#xff0c;CPU 时序的有关知识 ①振荡周期&#xff1a;为单片机提供定时信号的振荡源的周期&#xff08;晶振周期或…...

高速接口PCB布局指南(五)高速差分信号布线(三)

高速接口PCB布局指南&#xff08;五&#xff09;高速差分信号布线&#xff08;三&#xff09; 1.表面贴装器件焊盘不连续性缓解2.信号线弯曲3.高速信号建议的 PCB 叠层设计4.ESD/EMI 注意事项5.ESD/EMI 布局规则 tips&#xff1a;资料主要来自网络&#xff0c;仅供学习使用。 …...

MySQL使用报错1045 - Access denied for user ‘root‘@‘localhost‘ (using password: YES)

问题描述 设备&#xff1a;MacBook Pro macOS Monterey 12.1 MySQL版本&#xff1a;8.0.27 arm-64 描述&#xff1a;在使用Navicat连接电脑本地的数据库时&#xff0c;发现连接不上了&#xff0c;报了个错误1045 - Access denied for user rootlocalhost (using password: YES)…...

UE4 C++创建摄像机摇臂和相机并且设置Transform

新建MyPawn C类 .h #include "GameFramework/SpringArmComponent.h" //SpringArm组件 #include "Camera/CameraComponent.h" //Camera组件class 工程名称_API AMyPawn : public APawn { //定义组件变量 public:UPROPERTY(VisibleAnywhere, BlueprintRead…...

<网络安全>《14 日志审计系统》

1 概念 日志审计系统是用于全面收集企业IT系统中常见的安全设备、网络设备、数据库、服务器、应用系统、主机等设备所产生的日志&#xff08;包括运行、告警、操作、消息、状态等&#xff09;并进行存储、监控、审计、分析、报警、响应和报告的系统。 日志审计系统是一种用于…...

嵌入式软件设计方式与方法

1、嵌入式软件与设计模式 思从深而行从简 软件开发&#xff0c;难的不是编写软件&#xff0c;而是编写功能正常的软件。软件工程化才能保证软件质量和项目进度&#xff0c;而设计模式使代码开发真正工程化&#xff0c;设计模式是软件工程的基石。 所谓设计模式就是对常见问题的…...

ELAdmin 前端启动

开发工具 官方指导的是使用WebStorm&#xff0c;但是本人后端开发一枚&#xff0c;最终还是继续使用了 idea&#xff0c;主打一个能用就行。 idea正式版激活方式&#xff1a; 访问这个查找可用链接&#xff1a;https://3.jetbra.in/进入任意一个能用的里面&#xff0c;顶部提…...

完全让ChatGPT写一个风格迁移的例子,不改动任何代码

⭐️ 前言 小编让ChatGPT写一个风格迁移的例子&#xff0c;注意注意&#xff0c;代码无任何改动&#xff0c;直接运行&#xff0c;输出结果。 额。。。。这不是风格转换后的结果图。 ⭐️ 风格迁移基本原理 风格迁移是一种计算机视觉领域的图像处理技术&#xff0c;它的目标…...

查看jar包编译的jdk版本

解压jar包 jar xf xxx.jar 查看对象 javap -v Myclassname javap -v KafkaProducer.class |grep version -C 3 J2SE 8.0 52(0x33 hex) J2SE 7.0 51(0x32 hex) J2SE 6.0 50 (0x32 hex) J2SE 5.0 49 (0x31 hex) JDK 1.4 48 (0x30 hex) JDK 1.3 47 (0x2F hex) JDK 1.2 46 …...

未来之梦:畅想人工智能操控手机的辉煌时代

引言&#xff1a; 在当今数字化快速发展的时代&#xff0c;人工智能技术正日益深入我们的生活。其中&#xff0c;手机作为人们日常生活不可或缺的一部分&#xff0c;其未来将如何受到人工智能技术的影响&#xff0c;引发了广泛的关注和研究。本文将深入探讨人工智能操控手机的…...

产品经理--分享在项目中产品与研发之间会遇到的问题 在面试这一岗位时,面试官常问的问题之一,且分享两大原则来回答面试官这一问题

目录 一.STAR原则 1.1 简介 1.2 如何使用 1.3 举例说明 二.PDCA原则 2.1 简介 2.2 如何使用 2.3 运用场景 2.4 举例说明 三.产品与研发的沟通痛点 3.1 沟通痛点的原因 3.2 分享案例 前言 本篇会详细阐明作为一个产品经理会在项目遇到的问题&#xff0c;如&#xff1a;产…...

node环境打包js,webpack和rollup两个打包工具打包,能支持vue

引言 项目中经常用到共用的js&#xff0c;这里就需要用到共用js打包&#xff0c;这篇文章讲解两种打包方式&#xff0c;webpack打包和rollup打包两种方式 1、webpack打包js 1.1 在根目录创建 webpack.config.js&#xff0c;配置如下 const path require(path); module.expo…...

图数据库 之 Neo4j - 图数据库基础(2)

图数据库是一种专门用于存储、管理和查询图数据的数据库。与传统的关系型数据库不同&#xff0c;图数据库以图的形式存储数据&#xff0c;其中节点表示实体&#xff0c;边表示实体之间的关系。这种图数据模型非常适合表示复杂的关系和连接。 图数据库的定义和特点 图数据库是一…...

20240202在Ubuntu20.04.6下配置环境变量之后让nvcc --version显示正常

20240202在Ubuntu20.04.6下配置环境变量之后让nvcc --version显示正常 2024/2/2 20:19 在Ubuntu20.04.6下编译whiper.cpp的显卡模式的时候&#xff0c;报告nvcc异常了&#xff01; 百度&#xff1a;nvcc -v nvidia-cuda-toolkit rootrootrootroot-X99-Turbo:~/whisper.cpp$ WH…...

数字孪生网络攻防模拟与城市安全演练

在数字化浪潮的推动下&#xff0c;网络攻防模拟和城市安全演练成为维护社会稳定的不可或缺的环节。基于数字孪生技术我们能够在虚拟环境中进行高度真实的网络攻防模拟&#xff0c;为安全专业人员提供实战经验&#xff0c;从而提升应对网络威胁的能力。同时&#xff0c;在城市安…...

LeetCode、62.不同路径的数目(一)【简单,动态规划或递归】

文章目录 前言LeetCode、62.不同路径的数目(一)【简单&#xff0c;动态规划或递归】题目描述与分类思路思路1&#xff1a;动态规划思路2&#xff1a;递归实现简洁写法补充&#xff1a;2024.1.30 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、…...

re:从0开始的CSS学习之路 4. 长度单位

1. 长度单位 像素px&#xff1a;一个像素就是屏幕中一个不可分割的点。我们应用的屏幕实际上是由一个个的像素点构成的。 不同显示器的像素点大小也不同&#xff0c;在屏幕尺寸相同的情况下&#xff0c;像素越小&#xff0c;显示效果越清晰。 大部分浏览器默认字体大小是16px …...

golang开源定时任务调度框架

golang开源定时任务调度框架 Go语言中有很多开源的定时任务调度框架&#xff0c;以下几个是比较流行常用的&#xff1a; golang开源定时任务框架介绍 cron 一个基于Cron表达式的定时任务库&#xff0c;可以精确到秒级。它提供了简单易用的API来定义和管理定时任务&#xff…...

GridModel事件集合——yonBIP低代码

我们接着看表格相关的事件&#xff0c;用友的文档打不开&#xff0c;真的是天大的404&#xff0c;客观请看这个开发文档网址&#xff0c;找不到了&#xff0c;你说holy 不咯&#xff1f;http://tinper.org/mdf/&#xff08;如果有哪位小伙伴知道这个地址是不是迁移了的话&#…...

苹果macbook电脑删除数据恢复该怎么做?Mac电脑误删文件的恢复方法

苹果电脑删除数据恢复该怎么做&#xff1f;Mac电脑误删文件的恢复方法 如何在Mac上恢复误删除的文件&#xff1f;在日常使用Mac电脑时&#xff0c;无论是工作还是娱乐&#xff0c;我们都会创建和处理大量的文件。然而&#xff0c;有时候可能会不小心删除一些重要的文件&#x…...

2024年R2移动式压力容器充装证模拟考试题库及R2移动式压力容器充装理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年R2移动式压力容器充装证模拟考试题库及R2移动式压力容器充装理论考试试题是由安全生产模拟考试一点通提供&#xff0c;R2移动式压力容器充装证模拟考试题库是根据R2移动式压力容器充装最新版教材&#xff0c;R2…...

云开发超多功能工具箱组合微信小程序源码/附带流量主

这是一款云开发超多功能工具箱组合微信小程序源码附带流量主功能&#xff0c;小程序内包含了40余个功能&#xff0c;堪称全能工具箱了&#xff0c;大致功能如下&#xff1a; 证件照制作 | 垃圾分类查询 | 个性签名制作 二维码生成丨文字九宫格 | 手持弹幕丨照片压缩 | 照片编…...

挑战杯 python+深度学习+opencv实现植物识别算法系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的植物识别算法研究与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;4分 &#x1f9ff; 更多…...