flask庫(kù)中sessions.py的使用小結(jié)
在 Flask 中,Session(會(huì)話) 是一種用于在不同請(qǐng)求之間存儲(chǔ)用戶數(shù)據(jù)的機(jī)制。Flask 的 Session 默認(rèn)是基于 客戶端 Cookie 的,但數(shù)據(jù)會(huì)經(jīng)過加密簽名,防止篡改(但內(nèi)容本身是可讀的,除非額外加密)。
1. Flask Session 的基本使用
(1) 啟用 Session
Flask 的 Session 基于 flask.session,它是一個(gè)類似字典的對(duì)象。使用時(shí)需要設(shè)置 SECRET_KEY(用于簽名 Session 數(shù)據(jù),防止篡改):
from flask import Flask, session app = Flask(__name__) app.secret_key = 'your-secret-key-here' # 必須設(shè)置,否則 Session 無法工作
(2) 存儲(chǔ)和讀取 Session
from flask import Flask, session, request, redirect, url_for
app = Flask(__name__)
app.secret_key = 'your-secret-key'
@app.route('/login')
def login():
session['username'] = 'admin' # 存儲(chǔ) Session
session['logged_in'] = True # Session 可以存儲(chǔ)任意可序列化的數(shù)據(jù)
return "Logged in!"
@app.route('/dashboard')
def dashboard():
if session.get('logged_in'):
return f"Welcome, {session['username']}!"
else:
return redirect(url_for('login'))
@app.route('/logout')
def logout():
session.pop('username', None) # 移除 Session 中的某個(gè)鍵
session.clear() # 清空整個(gè) Session
return "Logged out!"(3) Session 的持久性(Permanent Session)
默認(rèn)情況下,Session 在瀏覽器關(guān)閉后失效。如果要讓 Session 長(zhǎng)期有效(基于 PERMANENT_SESSION_LIFETIME 配置):
from datetime import timedelta
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7) # 7天后過期
@app.route('/login')
def login():
session.permanent = True # 啟用持久 Session
session['username'] = 'admin'
return "Logged in (persistent)!"2. Flask Session 的工作原理
(1) 默認(rèn)實(shí)現(xiàn)(SecureCookieSession)
Flask 的 Session 默認(rèn)使用 SecureCookieSession,數(shù)據(jù)存儲(chǔ)在 客戶端 Cookie 中,但經(jīng)過簽名(防止篡改)。
數(shù)據(jù)格式:
{
"username": "admin",
"_fresh": True,
"_id": "abc123...",
"_permanent": True
}簽名機(jī)制:使用 itsdangerous 庫(kù)進(jìn)行簽名,確保數(shù)據(jù)不被篡改(但內(nèi)容可讀)。
(2) 如何修改 Session 存儲(chǔ)方式?
默認(rèn)的 Cookie Session 有大小限制(通常 4KB),如果需要存儲(chǔ)大量數(shù)據(jù),可以改用 服務(wù)端 Session(如 Redis、數(shù)據(jù)庫(kù)):
from flask_session import Session # 需要安裝 flask-session app.config['SESSION_TYPE'] = 'redis' # 可選 redis, memcached, filesystem 等 app.config['SESSION_PERMANENT'] = True app.config['SESSION_USE_SIGNER'] = True # 是否簽名 Cookie app.config['SESSION_KEY_PREFIX'] = 'myapp:' # Redis 鍵前綴 Session(app) # 替換默認(rèn)的 Session 實(shí)現(xiàn)
然后 flask.session 會(huì)自動(dòng)使用 Redis 存儲(chǔ)數(shù)據(jù),而不是 Cookie。
3. Session 的安全配置
(1) 安全相關(guān)的 Cookie 設(shè)置
app.config.update(
SESSION_COOKIE_NAME='my_session', # Cookie 名稱
SESSION_COOKIE_HTTPONLY=True, # 禁止 JavaScript 訪問
SESSION_COOKIE_SECURE=True, # 僅 HTTPS 傳輸
SESSION_COOKIE_SAMESITE='Lax', # 防 CSRF(Strict/Lax/None)
SESSION_COOKIE_PARTITIONED=True, # 跨站 Cookie 隔離(CHIPS)
)(2) 防止 Session 劫持
- 使用
SESSION_USE_SIGNER=True(默認(rèn)啟用)防止篡改。 - 避免在 Session 中存儲(chǔ)敏感信息(如密碼),因?yàn)?Cookie 內(nèi)容可被用戶讀?。词购灻?/li>
4. 常見問題
(1)RuntimeError: The session is unavailable because no secret key was set.
原因:未設(shè)置 SECRET_KEY。
解決:
app.secret_key = 'your-secret-key' # 必須設(shè)置
(2) Session 數(shù)據(jù)不持久
原因:默認(rèn) Session 在瀏覽器關(guān)閉后失效。
解決:
session.permanent = True app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=30)
(3) 如何強(qiáng)制 Session 過期?
@app.route('/clear_session')
def clear_session():
session.clear() # 清空 Session
return "Session cleared!"5. 總結(jié)
| 特性 | 說明 |
|---|---|
| 默認(rèn)存儲(chǔ) | 客戶端 Cookie(簽名防篡改) |
| 持久性 | session.permanent = True + PERMANENT_SESSION_LIFETIME |
| 安全配置 | HTTPOnly、Secure、SameSite |
| 擴(kuò)展存儲(chǔ) | 使用 flask-session 支持 Redis、數(shù)據(jù)庫(kù)等 |
| 適用場(chǎng)景 | 小型數(shù)據(jù)(如用戶登錄狀態(tài)),大數(shù)據(jù)需用服務(wù)端存儲(chǔ) |
如果需要更安全的 Session 方案,建議:
- 使用 服務(wù)端 Session(Redis) 替代 Cookie。
- 避免存儲(chǔ)敏感數(shù)據(jù)在 Session 中。
- 啟用
Secure+SameSite防 CSRF。
Sessions.py
from __future__ import annotations
import collections.abc as c
import hashlib
import typing as t
from collections.abc import MutableMapping
from datetime import datetime
from datetime import timezone
from itsdangerous import BadSignature
from itsdangerous import URLSafeTimedSerializer
from werkzeug.datastructures import CallbackDict
from .json.tag import TaggedJSONSerializer
if t.TYPE_CHECKING: # pragma: no cover
import typing_extensions as te
from .app import Flask
from .wrappers import Request
from .wrappers import Response
class SessionMixin(MutableMapping[str, t.Any]):
"""Expands a basic dictionary with session attributes."""
@property
def permanent(self) -> bool:
"""This reflects the ``'_permanent'`` key in the dict."""
return self.get("_permanent", False)
@permanent.setter
def permanent(self, value: bool) -> None:
self["_permanent"] = bool(value)
#: Some implementations can detect whether a session is newly
#: created, but that is not guaranteed. Use with caution. The mixin
# default is hard-coded ``False``.
new = False
#: Some implementations can detect changes to the session and set
#: this when that happens. The mixin default is hard coded to
#: ``True``.
modified = True
#: Some implementations can detect when session data is read or
#: written and set this when that happens. The mixin default is hard
#: coded to ``True``.
accessed = True
class SecureCookieSession(CallbackDict[str, t.Any], SessionMixin):
"""Base class for sessions based on signed cookies.
This session backend will set the :attr:`modified` and
:attr:`accessed` attributes. It cannot reliably track whether a
session is new (vs. empty), so :attr:`new` remains hard coded to
``False``.
"""
#: When data is changed, this is set to ``True``. Only the session
#: dictionary itself is tracked; if the session contains mutable
#: data (for example a nested dict) then this must be set to
#: ``True`` manually when modifying that data. The session cookie
#: will only be written to the response if this is ``True``.
modified = False
#: When data is read or written, this is set to ``True``. Used by
# :class:`.SecureCookieSessionInterface` to add a ``Vary: Cookie``
#: header, which allows caching proxies to cache different pages for
#: different users.
accessed = False
def __init__(
self,
initial: c.Mapping[str, t.Any] | c.Iterable[tuple[str, t.Any]] | None = None,
) -> None:
def on_update(self: te.Self) -> None:
self.modified = True
self.accessed = True
super().__init__(initial, on_update)
def __getitem__(self, key: str) -> t.Any:
self.accessed = True
return super().__getitem__(key)
def get(self, key: str, default: t.Any = None) -> t.Any:
self.accessed = True
return super().get(key, default)
def setdefault(self, key: str, default: t.Any = None) -> t.Any:
self.accessed = True
return super().setdefault(key, default)
class NullSession(SecureCookieSession):
"""Class used to generate nicer error messages if sessions are not
available. Will still allow read-only access to the empty session
but fail on setting.
"""
def _fail(self, *args: t.Any, **kwargs: t.Any) -> t.NoReturn:
raise RuntimeError(
"The session is unavailable because no secret "
"key was set. Set the secret_key on the "
"application to something unique and secret."
)
__setitem__ = __delitem__ = clear = pop = popitem = update = setdefault = _fail # noqa: B950
del _fail
class SessionInterface:
"""The basic interface you have to implement in order to replace the
default session interface which uses werkzeug's securecookie
implementation. The only methods you have to implement are
:meth:`open_session` and :meth:`save_session`, the others have
useful defaults which you don't need to change.
The session object returned by the :meth:`open_session` method has to
provide a dictionary like interface plus the properties and methods
from the :class:`SessionMixin`. We recommend just subclassing a dict
and adding that mixin::
class Session(dict, SessionMixin):
pass
If :meth:`open_session` returns ``None`` Flask will call into
:meth:`make_null_session` to create a session that acts as replacement
if the session support cannot work because some requirement is not
fulfilled. The default :class:`NullSession` class that is created
will complain that the secret key was not set.
To replace the session interface on an application all you have to do
is to assign :attr:`flask.Flask.session_interface`::
app = Flask(__name__)
app.session_interface = MySessionInterface()
Multiple requests with the same session may be sent and handled
concurrently. When implementing a new session interface, consider
whether reads or writes to the backing store must be synchronized.
There is no guarantee on the order in which the session for each
request is opened or saved, it will occur in the order that requests
begin and end processing.
.. versionadded:: 0.8
"""
#: :meth:`make_null_session` will look here for the class that should
#: be created when a null session is requested. Likewise the
#: :meth:`is_null_session` method will perform a typecheck against
#: this type.
null_session_class = NullSession
#: A flag that indicates if the session interface is pickle based.
#: This can be used by Flask extensions to make a decision in regards
#: to how to deal with the session object.
#:
#: .. versionadded:: 0.10
pickle_based = False
def make_null_session(self, app: Flask) -> NullSession:
"""Creates a null session which acts as a replacement object if the
real session support could not be loaded due to a configuration
error. This mainly aids the user experience because the job of the
null session is to still support lookup without complaining but
modifications are answered with a helpful error message of what
failed.
This creates an instance of :attr:`null_session_class` by default.
"""
return self.null_session_class()
def is_null_session(self, obj: object) -> bool:
"""Checks if a given object is a null session. Null sessions are
not asked to be saved.
This checks if the object is an instance of :attr:`null_session_class`
by default.
"""
return isinstance(obj, self.null_session_class)
def get_cookie_name(self, app: Flask) -> str:
"""The name of the session cookie. Uses``app.config["SESSION_COOKIE_NAME"]``."""
return app.config["SESSION_COOKIE_NAME"] # type: ignore[no-any-return]
def get_cookie_domain(self, app: Flask) -> str | None:
"""The value of the ``Domain`` parameter on the session cookie. If not set,
browsers will only send the cookie to the exact domain it was set from.
Otherwise, they will send it to any subdomain of the given value as well.
Uses the :data:`SESSION_COOKIE_DOMAIN` config.
.. versionchanged:: 2.3
Not set by default, does not fall back to ``SERVER_NAME``.
"""
return app.config["SESSION_COOKIE_DOMAIN"] # type: ignore[no-any-return]
def get_cookie_path(self, app: Flask) -> str:
"""Returns the path for which the cookie should be valid. The
default implementation uses the value from the ``SESSION_COOKIE_PATH``
config var if it's set, and falls back to ``APPLICATION_ROOT`` or
uses ``/`` if it's ``None``.
"""
return app.config["SESSION_COOKIE_PATH"] or app.config["APPLICATION_ROOT"] # type: ignore[no-any-return]
def get_cookie_httponly(self, app: Flask) -> bool:
"""Returns True if the session cookie should be httponly. This
currently just returns the value of the ``SESSION_COOKIE_HTTPONLY``
config var.
"""
return app.config["SESSION_COOKIE_HTTPONLY"] # type: ignore[no-any-return]
def get_cookie_secure(self, app: Flask) -> bool:
"""Returns True if the cookie should be secure. This currently
just returns the value of the ``SESSION_COOKIE_SECURE`` setting.
"""
return app.config["SESSION_COOKIE_SECURE"] # type: ignore[no-any-return]
def get_cookie_samesite(self, app: Flask) -> str | None:
"""Return ``'Strict'`` or ``'Lax'`` if the cookie should use the
``SameSite`` attribute. This currently just returns the value of
the :data:`SESSION_COOKIE_SAMESITE` setting.
"""
return app.config["SESSION_COOKIE_SAMESITE"] # type: ignore[no-any-return]
def get_cookie_partitioned(self, app: Flask) -> bool:
"""Returns True if the cookie should be partitioned. By default, uses
the value of :data:`SESSION_COOKIE_PARTITIONED`.
.. versionadded:: 3.1
"""
return app.config["SESSION_COOKIE_PARTITIONED"] # type: ignore[no-any-return]
def get_expiration_time(self, app: Flask, session: SessionMixin) -> datetime | None:
"""A helper method that returns an expiration date for the session
or ``None`` if the session is linked to the browser session. The
default implementation returns now + the permanent session
lifetime configured on the application.
"""
if session.permanent:
return datetime.now(timezone.utc) + app.permanent_session_lifetime
return None
def should_set_cookie(self, app: Flask, session: SessionMixin) -> bool:
"""Used by session backends to determine if a ``Set-Cookie`` header
should be set for this session cookie for this response. If the session
has been modified, the cookie is set. If the session is permanent and
the ``SESSION_REFRESH_EACH_REQUEST`` config is true, the cookie is
always set.
This check is usually skipped if the session was deleted.
.. versionadded:: 0.11
"""
return session.modified or (
session.permanent and app.config["SESSION_REFRESH_EACH_REQUEST"]
)
def open_session(self, app: Flask, request: Request) -> SessionMixin | None:
"""This is called at the beginning of each request, after
pushing the request context, before matching the URL.
This must return an object which implements a dictionary-like
interface as well as the :class:`SessionMixin` interface.
This will return ``None`` to indicate that loading failed in
some way that is not immediately an error. The request
context will fall back to using :meth:`make_null_session`
in this case.
"""
raise NotImplementedError()
def save_session(
self, app: Flask, session: SessionMixin, response: Response
) -> None:
"""This is called at the end of each request, after generating
a response, before removing the request context. It is skipped
if :meth:`is_null_session` returns ``True``.
"""
raise NotImplementedError()
session_json_serializer = TaggedJSONSerializer()
def _lazy_sha1(string: bytes = b"") -> t.Any:
"""Don't access ``hashlib.sha1`` until runtime. FIPS builds may not include
SHA-1, in which case the import and use as a default would fail before the
developer can configure something else.
"""
return hashlib.sha1(string)
class SecureCookieSessionInterface(SessionInterface):
"""The default session interface that stores sessions in signed cookies
through the :mod:`itsdangerous` module.
"""
#: the salt that should be applied on top of the secret key for the
#: signing of cookie based sessions.
salt = "cookie-session"
#: the hash function to use for the signature. The default is sha1
digest_method = staticmethod(_lazy_sha1)
#: the name of the itsdangerous supported key derivation. The default
#: is hmac.
key_derivation = "hmac"
#: A python serializer for the payload. The default is a compact
#: JSON derived serializer with support for some extra Python types
#: such as datetime objects or tuples.
serializer = session_json_serializer
session_class = SecureCookieSession
def get_signing_serializer(self, app: Flask) -> URLSafeTimedSerializer | None:
if not app.secret_key:
return None
keys: list[str | bytes] = []
if fallbacks := app.config["SECRET_KEY_FALLBACKS"]:
keys.extend(fallbacks)
keys.append(app.secret_key) # itsdangerous expects current key at top
return URLSafeTimedSerializer(
keys, # type: ignore[arg-type]
salt=self.salt,
serializer=self.serializer,
signer_kwargs={
"key_derivation": self.key_derivation,
"digest_method": self.digest_method,
},
)
def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None:
s = self.get_signing_serializer(app)
if s is None:
return None
val = request.cookies.get(self.get_cookie_name(app))
if not val:
return self.session_class()
max_age = int(app.permanent_session_lifetime.total_seconds())
try:
data = s.loads(val, max_age=max_age)
return self.session_class(data)
except BadSignature:
return self.session_class()
def save_session(
self, app: Flask, session: SessionMixin, response: Response
) -> None:
name = self.get_cookie_name(app)
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
secure = self.get_cookie_secure(app)
partitioned = self.get_cookie_partitioned(app)
samesite = self.get_cookie_samesite(app)
httponly = self.get_cookie_httponly(app)
# Add a "Vary: Cookie" header if the session was accessed at all.
if session.accessed:
response.vary.add("Cookie")
# If the session is modified to be empty, remove the cookie.
# If the session is empty, return without setting the cookie.
if not session:
if session.modified:
response.delete_cookie(
name,
domain=domain,
path=path,
secure=secure,
partitioned=partitioned,
samesite=samesite,
httponly=httponly,
)
response.vary.add("Cookie")
return
if not self.should_set_cookie(app, session):
return
expires = self.get_expiration_time(app, session)
val = self.get_signing_serializer(app).dumps(dict(session)) # type: ignore[union-attr]
response.set_cookie(
name,
val,
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure,
partitioned=partitioned,
samesite=samesite,
)
response.vary.add("Cookie")
1. 會(huì)話(Session)的核心類
(1)SessionMixin
作用:為字典形式的 Session 提供擴(kuò)展屬性。
關(guān)鍵屬性:
permanent:標(biāo)記 Session 是否為持久會(huì)話(基于_permanent鍵值)。new:標(biāo)記 Session 是否為新創(chuàng)建的(默認(rèn)為False)。modified:標(biāo)記 Session 是否被修改(默認(rèn)為True)。accessed:標(biāo)記 Session 是否被訪問(默認(rèn)為True)。
(2)SecureCookieSession
作用:基于簽名 Cookie 的默認(rèn) Session 實(shí)現(xiàn)(繼承自 CallbackDict 和 SessionMixin)。
特點(diǎn):
- 自動(dòng)跟蹤修改狀態(tài)(
modified)和訪問狀態(tài)(accessed)。 - 數(shù)據(jù)變更時(shí)會(huì)觸發(fā)回調(diào),確保狀態(tài)同步。
(3)NullSession
作用:當(dāng)未配置密鑰時(shí),提供一個(gè)安全的空 Session 替代品。
行為:
- 允許讀取操作(返回空值)。
- 拒絕寫入操作(直接拋出
RuntimeError)。
2. 會(huì)話接口(SessionInterface)
(1) 核心方法
open_session(app, request)
功能:在請(qǐng)求開始時(shí)加載 Session。
返回:需實(shí)現(xiàn)類字典接口 +SessionMixin的對(duì)象,失敗時(shí)返回None(觸發(fā)NullSession)。save_session(app, session, response)
功能:在請(qǐng)求結(jié)束時(shí)保存 Session 到響應(yīng)。
注意:若is_null_session(session)為True則跳過。
(2) Cookie 配置方法
get_cookie_name():從配置SESSION_COOKIE_NAME獲取 Cookie 名稱。get_cookie_domain():控制 Cookie 的Domain屬性(默認(rèn)無子域名共享)。get_cookie_secure():根據(jù)SESSION_COOKIE_SECURE決定是否僅 HTTPS 傳輸。get_cookie_samesite():配置SameSite防 CSRF(Strict/Lax)。get_cookie_partitioned():是否啟用Partitioned屬性(用于跨站 Cookie 隔離)。
(3) 輔助邏輯
should_set_cookie():決定是否設(shè)置Set-Cookie頭(基于修改狀態(tài)或SESSION_REFRESH_EACH_REQUEST)。make_null_session():生成NullSession實(shí)例。is_null_session():檢查對(duì)象是否為無效 Session。
3. 默認(rèn)實(shí)現(xiàn)(SecureCookieSessionInterface)
(1) 安全特性
簽名機(jī)制:使用 itsdangerous.URLSafeTimedSerializer。
- 支持密鑰輪換(
SECRET_KEY_FALLBACKS)。 - 可配置鹽值(
salt)、哈希算法(如sha1)和密鑰派生方式(如hmac)。
數(shù)據(jù)序列化:通過 TaggedJSONSerializer 處理 Python 特殊類型(如 datetime)。
(2) 工作流程
讀取 Session
- 從請(qǐng)求的 Cookie 中加載數(shù)據(jù)。
- 驗(yàn)證簽名和時(shí)間戳(防止篡改和過期會(huì)話)。
- 失敗時(shí)返回空 Session。
保存 Session
- 若 Session 為空且被修改 → 刪除 Cookie。
- 若需更新(
should_set_cookie為True)→ 寫入簽名后的數(shù)據(jù)到 Cookie。 - 自動(dòng)設(shè)置
Vary: Cookie頭以適配緩存。
(3) 配置示例
app.config.update(
SECRET_KEY="your-secret-key",
SESSION_COOKIE_NAME="my_session",
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_SAMESITE="Lax",
PERMANENT_SESSION_LIFETIME=timedelta(days=7),
)4. 設(shè)計(jì)思想
- 客戶端存儲(chǔ):Session 數(shù)據(jù)默認(rèn)通過 Cookie 存儲(chǔ)(節(jié)省服務(wù)端資源)。
- 安全優(yōu)先:所有數(shù)據(jù)簽名防篡改,且支持安全相關(guān)的 Cookie 屬性。
- 靈活擴(kuò)展:通過實(shí)現(xiàn)
SessionInterface可輕松切換為服務(wù)端 Session(如 Redis 存儲(chǔ))。
常見問題
- 密鑰缺失:未設(shè)置
SECRET_KEY時(shí),所有 Session 操作將觸發(fā)NullSession的異常。 - 性能注意:Cookie 大小受限(通常不超過 4KB),復(fù)雜數(shù)據(jù)需考慮服務(wù)端存儲(chǔ)方案。
如果需要進(jìn)一步分析特定部分(如自定義 Session 存儲(chǔ)),可以深入探討具體實(shí)現(xiàn)方式。
到此這篇關(guān)于flask庫(kù)中sessions.py的使用小結(jié)的文章就介紹到這了,更多相關(guān)flask sessions.py內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Pycharm使用之設(shè)置代碼字體大小和顏色主題的教程
今天小編就為大家分享一篇Pycharm使用之設(shè)置代碼字體大小和顏色主題的教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07
python抓取網(wǎng)頁(yè)內(nèi)容并進(jìn)行語(yǔ)音播報(bào)的方法
今天小編就為大家分享一篇python抓取網(wǎng)頁(yè)內(nèi)容并進(jìn)行語(yǔ)音播報(bào)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-12-12
Python中import的用法陷阱解決盤點(diǎn)小結(jié)
這篇文章主要為大家介紹了Python中import的用法陷阱解決盤點(diǎn)小結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
python基于socket實(shí)現(xiàn)網(wǎng)絡(luò)廣播的方法
這篇文章主要介紹了python基于socket實(shí)現(xiàn)網(wǎng)絡(luò)廣播的方法,涉及Python操作socket的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
利用Flask實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)增刪改查API的全過程
這篇文章主要介紹了如何用Flask實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)增刪改查API,本文圍繞用Flask實(shí)現(xiàn)MySQL數(shù)據(jù)庫(kù)增刪改查(CRUD)API展開,并附上完整代碼示例,幫助開發(fā)者掌握Flask結(jié)合MySQL開發(fā)API的方法,需要的朋友可以參考下2025-09-09
利用Pandas 創(chuàng)建空的DataFrame方法
下面小編就為大家分享一篇利用Pandas 創(chuàng)建空的DataFrame方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-04-04
Python高級(jí)文件操作之shutil庫(kù)詳解
這篇文章主要介紹了Python高級(jí)文件操作之shutil庫(kù)詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python的小伙伴們有很大的幫助,需要的朋友可以參考下2021-05-05

