记忆

Python

试用

按文档化的 Python 规则手册和固定检查清单排查、审阅与编写代码。

它能做什么

输出代码前会先核对"核心规则"和"产出清单"——可变默认参数、`is` 与 `==`、显式编码、超时、上下文管理器、并发模型选择。调试、打包、类型检查、测试、性能、并发等问题分别路由到对应的子指南(debugging.md、packaging.md、concurrency.md、testing.md 等)。同时按用户配置(最低 Python 版本、包管理器、类型严格度、

技能文档

User preferences live in ~/Clawic/data/py/config.yaml (see Configuration); nothing else is stored on the user's machine. If you have data at an old location (~/py/ or ~/clawic/py/), move it to ~/Clawic/data/py/.

When To Use

  • Writing or reviewing Python — scan Core Rules and Output Gates before committing
  • Debugging wrong results without exceptions: state leaking across calls, aliased mutations, silent coercion
  • Any traceback whose cause is not obvious in ten seconds, plus hangs, memory growth, and segfaults
  • Environment and dependency work: venvs, lockfiles, editable installs, publishing, version upgrades
  • Choosing a concurrency model, a data model, or a typing strategy, and living with the consequences
  • Hardening a script into a tool: arguments, exit codes, logging, timeouts, retries, untrusted input
  • Not for library-specific issues — pandas, numpy, django, fastapi, flask have their own skills

Quick Reference

SituationPlay
Wrong value, no exceptionrepr() at input, midpoint, output; the first wrong one is the bug — suspect aliasing, coercion, stale default → debugging.md
A traceback you have not seen beforeMessage → cause table, then the matching chain → debugging.md
Installed it, still ModuleNotFoundErrorWrong interpreter: check sys.executable, then use python -m pip → packaging.md
venvs, lockfiles, uv vs pip vs poetry, publishingApplications pin everything with hashes; libraries declare ranges → packaging.md
cannot import name X from partially initialized moduleCircular import; switch to import a + a.f() before restructuring → imports.md
is vs ==, float rounding, money, NaN, string surgeryis only for None/True/False/sentinels; Decimal from strings → types.md
Aliasing, copies, ordering, membership cost[[]]*3 shares one list; x in list is O(n) → collections.md
State leaks across calls: defaults, closures, decorators, generatorsDefaults evaluate once, at def time → functions.md
Class design: shared attributes, hashability, MRO, __slots____eq__ without __hash__ makes instances unhashable → classes.md
dict vs dataclass vs NamedTuple vs pydantic; validating inputValidate once at the boundary, plain objects inside → data-modeling.md
Slow, hanging, or racy: GIL, threads, asyncio, multiprocessingPure-Python CPU → processes; I/O → threads or asyncio → concurrency.md
Too slow, or too much memoryProfile first, then fix the top line or nothing → performance.md
Tests pass but should not; mock patches nothing; async tests skippedPatch where the name is USED; autospec=True → testing.md
mypy or pyright errors, annotating a legacy codebaseFreeze a baseline, then ratchet one package at a time → type-checking.md
Formatting, import order, lint rules, pre-commit, style review commentsOne formatter owns layout; ruff check for bugs; same versions in hook and CI → linting.md
UnicodeDecodeError, CSV and JSON traps, atomic writes, temp filesDeclare encoding="utf-8"; write temp then os.replace → files.md
Timezones, DST, parsing dates, measuring elapsed timeAware datetimes everywhere; time.monotonic() for durations → datetime.md
Calling git/ffmpeg/anything external, hanging or failing silentlyrun([...], check=True, timeout=…), never shell=True with interpolation → subprocess.md
Writing a script or CLI: arguments, exit codes, pipes, signalssys.exit(main()); stdout for data, stderr for logs → cli.md
Nothing appears in the logs, or deciding what to logFour gates: basicConfig no-op, logger level, handler level, propagation → logging.md
Exception design, chaining, retries, timeoutsraise X from exc; exponential backoff with jitter → errors.md
Calling an HTTP API: sessions, status codes, redirects, streaming a big bodyOne client per process; raise_for_status() before .json() → http.md
A local database, cache, or queue in a file; database is lockedWAL plus an explicit busy timeout; one connection per thread → sqlite.md
Untrusted input: pickle, eval, SQL, paths, archives, secretsUnpickling executes code; parameterize SQL; contain paths → security.md
"Is there something in the stdlib for this?"Counter, deque, bisect, itertools, pathlib, secrets, sqlite3 → stdlib.md
Notebook works for you and nobody else; results change between runsRestart and run all; %pip not !pip; strip outputs before committing → notebooks.md
Upgrading Python, choosing a version, a module that vanishedRun the suite with -W error::DeprecationWarning on the OLD version first → versions.md
Anything elseCore Rules below, then reproduce with python -I -c '' and re-add one thing at a time

Each file above is one sub-job and is self-contained: read SKILL.md by default, open exactly one guide when the situation matches.

Core Rules

  1. No mutable defaults: def f(xs=None) then if xs is None: xs = []. Never xs = xs or [] — a caller passing an empty list to be filled gets a fresh list instead; their reference stays empty.
  2. is only for None, True, False, and sentinel objects; == for everything else. Interning makes is on ints and strings pass in tests and fail in production (types.md).
  3. Never mutate the collection you iterate — dicts raise RuntimeError, lists silently skip elements. Iterate a copy (for x in list(xs)) or collect changes and apply after.
  4. Match concurrency to workload: pure-Python CPU → multiprocessing; I/O → threads or asyncio; threads never speed up pure-Python CPU work, because the GIL serializes bytecode (concurrency.md).
  5. except Exception:, never bare except: — bare also catches KeyboardInterrupt and SystemExit, making the process unkillable. Re-raise with bare raise, keeping the original traceback (errors.md).
  6. Files, locks, sockets, connections: always with. CPython's refcounting closes leaked handles by accident; exceptions and other interpreters (PyPy) expose the leak.
  7. Money and exact decimals: decimal.Decimal('1.10') from strings — Decimal(1.1) imports the float error it was meant to avoid. Float comparisons via math.isclose (types.md).
  8. Declare encoding='utf-8' at every I/O boundary — the default follows the platform locale until UTF-8 becomes the default (PEP 686, python >=3.15), so the code breaks first on Windows and in lean containers (files.md).
  9. Guard entry points with if __name__ == "__main__": — top-level code runs on every import and again in every multiprocessing spawn child (imports.md).

Version Floors

The syntax and stdlib floors that shape everyday code. Individual guides carry additional floors — mostly changed defaults and new keyword arguments — inline in this same python >=X.Y form, next to the instruction each one gates. Support windows, removals, and the upgrade procedure: versions.md.

FeatureNeeds
Guaranteed dict insertion order, dataclasses, breakpoint(), from __future__ import annotations, sys.stdout.reconfigurepython >=3.7
Walrus :=, positional-only /, functools.cached_property, TypedDict/Protocol/Literal/Final, basicConfig(force=), self-documenting f"{value=}"python >=3.8
Builtin generics list[int], d1 | d2 (dict merge), zoneinfo, removeprefix/removesuffix, functools.cache, asyncio.to_thread, importlib.resources.files, Path.is_relative_to, graphlib, argparse.BooleanOptionalAction, executor.shutdown(cancel_futures=)python >=3.9
X | Y unions, match, zip(strict=True), dataclass slots=/kw_only=, itertools.pairwise, ParamSpec, EncodingWarning and -X warn_default_encodingpython >=3.10
ExceptionGroup/except*, asyncio.TaskGroup, tomllib, Self, StrEnum, exc.add_note(), contextlib.chdir, full-ISO fromisoformat, NotRequiredpython >=3.11
PEP 695 generics (def f[T]()), @override, itertools.batched, tarfile(filter="data")python >=3.12
Experimental free-threaded build; PEP 594 module removals (cgi, telnetlib, …)python >=3.13
forkserver as the Linux multiprocessing default, lazy annotations (PEP 649)python >=3.14
UTF-8 as the default text encoding everywhere (PEP 686), retiring the locale defaultpython >=3.15

Output Gates

Before delivering Python code, check:

  • No mutable default argument, and no xs or [] where an empty argument is meaningful
  • Every text open, subprocess, and decode boundary declares encoding="utf-8"; every file, lock, socket, and connection is acquired in a with
  • Every network, subprocess, lock, and queue call has a timeout
  • Exceptions: narrowest class caught, chained with from, nothing swallowed without a log line or a written reason
  • Logging through a module logger with lazy %s arguments and no secrets
  • Syntax and stdlib stay within min_python; annotations match type_strictness
  • Nothing user-supplied reaches eval, pickle, a shell string, an SQL string, or a path join without containment
  • The new test was seen failing without the fix in place — change_workflow decides when that run happens, never whether it happened

Configuration

User-dependent variables. Defaults apply until the user states a preference; store them in ~/Clawic/data/py/config.yaml. Never interview the user — record a preference the moment it is stated.

VariableTypeDefaultEffect
min_python3.9 | 3.10 | 3.11 | 3.12 | 3.13 | 3.143.11Gates which Version Floors features may be emitted unguarded, and which fallback appears instead
package_managerpip | uv | poetry | pdm | condapipChooses the install, lock, and venv commands in every example (packaging.md)
type_strictnessnone | gradual | strictgradualHow far annotations go: none skips hints, gradual annotates public boundaries, strict turns on disallow_untyped_defs (type-checking.md)
test_runnerpytest | unittestpytestShape of emitted tests, fixtures, and mocking guidance (testing.md)
target_oslinux | macos | windows | crosscrossPath, encoding, and multiprocessing start-method assumptions; cross flags all three
src_layoutsrc | flatsrcProject scaffolding, editable-install and import advice (packaging.md)
line_lengthnumber (79-120)88Formatting of emitted code and the ruff/black config value (linting.md)
change_workflowtest-first | fix-firsttest-firstOrder of the work: test-first writes the failing test before the fix, fix-first patches first and backfills the test against the reverted change (testing.md)

Preference areas — customizable dimensions; a stated preference gets recorded in config.yaml and applied:

  • Tooling: formatter and linter (ruff vs black+flake8), checker (mypy vs pyright), task runner, notebook vs module workflow — affects every emitted config block (linting.md)
  • Conventions: docstring style (Google/NumPy/reST), naming, module granularity, error-message phrasing — affects generated code and review comments
  • Platform: deployment target (container, serverless, desktop, embedded), CPU architecture, private package index, CI provider — affects packaging.md and versions.md guidance
  • Safety posture: how aggressively to flag pickle, eval, shell=True, missing timeouts and unpinned dependencies — affects security.md and cli.md
  • Dependencies: stdlib-only constraints, banned or mandated libraries (requests vs httpx, pydantic vs dataclasses), tolerance for new transitive dependencies — affects every recommendation
  • Output format: whole file vs minimal diff, how much explanation, whether tests accompany every change — affects the shape of the answer, never the correctness rules
  • Work order: which gates run before a change is proposed rather than after — checker and suite green first, a plan approved before editing, a --dry-run pass on destructive scripts, a profile before any optimization — affects the sequence of every task, never the correctness rules

Traps

TrapWhy it failsDo instead
Bare pip installInstalls into whatever interpreter is first on PATH — the "installed it, still ModuleNotFoundError" looppython -m pip install inside an activated venv (packaging.md)
except Exception: passTurns a crash into a wrong answer three layers awayLog with logger.exception, or write down why this failure is expected (errors.md)
assert user.is_admin as a checkpython -O removes every assert, including that oneRaise explicitly (security.md)
time.time() to measure a durationNTP can step the clock backwards mid-measurement and produce negative elapsed timetime.monotonic() (datetime.md)
datetime.utcnow()Returns a NAIVE datetime holding UTC: compares wrong against aware values, deprecated in python >=3.12datetime.now(timezone.utc) (datetime.md)
f-strings inside logging callsFormats even when the level is disabled, and every line becomes a unique string to the aggregatorlog.info("user %s", uid) (logging.md)
sys.path.append(...) to fix an importWorks from one entry point, breaks under pytest, packaging, and any other cwdEditable install with a src/ layout (imports.md)
shell=True with an interpolated valueCommand injection — and /bin/sh is not bashArgument list; shlex.quote if a shell is unavoidable (subprocess.md)
verify=False to silence an SSL errorDisables peer authentication for every request in the processInstall the CA bundle (security.md)
pickle across a process, user, or network boundaryUnpickling executes attacker-controlled code before you can inspect itJSON/msgpack, or an HMAC-signed payload (security.md)
raise e when re-raisingAppends the current line and hides where the exception really came fromBare raise (errors.md)
Type hints treated as validationNever enforced at runtime: def f(x: int) happily takes a stringChecker in CI plus runtime validation at the boundary (type-checking.md)
x in list or list.pop(0) inside a loopO(n) per operation makes the loop O(n²)set for membership, deque for both ends (collections.md)

Where Experts Disagree

  • asyncio vs threads. asyncio is not "faster Python": for moderate I/O concurrency, ThreadPoolExecutor matches it with far less ceremony. Boundary: high connection counts AND an async-native stack end to end → asyncio; one blocking driver anywhere in the chain forfeits the benefit (concurrency.md).
  • How much typing. The strict school annotates everything and treats Any as a defect; the pragmatic school types boundaries and lets internals be inferred. Boundary: libraries and cross-team APIs → annotate fully; single-owner scripts and glue → boundaries only. Either way, one checker in CI (type-checking.md).
  • Packaging tooling. venv + pip exists on every machine and surprises nobody; uv/poetry/hatch are faster and manage more. Boundary: a project with a real dependency problem, many contributors, or several interpreters justifies the tool; one that installs three libraries does not (packaging.md).
  • EAFP vs LBYL. Python's culture prefers try/except over pre-checking, and it is genuinely more correct under concurrency — the file can disappear between exists() and open(). Boundary: LBYL when the operation is expensive or irreversible, EAFP when the failure is cheap and the race is real.

More Clawic skills, get them at https://clawic.com/skills/py (install if the user confirms):

  • pandas — DataFrame-specific traps and idioms
  • fastapi — async web APIs in Python
  • django — Django ORM and framework patterns
  • profiling — when the question is "why is it slow", measure first
  • debugging — language-agnostic fault isolation (bisection, hypothesis discipline, minimal repro); the Python-specific version of that job is this skill's debugging.md

Feedback

Part of Clawic, the verified skill library. Get this skill: https://clawic.com/skills/py.

相关技能

在本地磁盘以分类纯 Markdown 文件保存需要长期留存的事实,与智能体内置记忆并存。

作者 Iván556 次安装18 星标

诊断生产力系统反复失效的根因,给出最小干预——容量测算、瓶颈定位、可靠的本地记录。

作者 Iván855 次安装69 星标

执行 Git 操作(提交、分支、合并、变基、冲突解决与恢复)时强制套用安全规则。

作者 Iván533 次安装31 星标

把自然语言描述转为结构化 JSON,并由 mcp-diagram-generator MCP 服务生成 Draw.io、Mermaid 或 Excalidraw 图表文件。

作者 nssa.io1.0k 次安装47 星标

以 AI 机器人身份加入视频会议,提供语音、虚拟形象与屏幕共享四种模式。

作者 johnpatternai21 次安装8 星标

ivangdavila 的更多技能

浏览全部技能

诊断生产力系统反复失效的根因,给出最小干预——容量测算、瓶颈定位、可靠的本地记录。

作者 Iván855 次安装69 星标

执行 Git 操作(提交、分支、合并、变基、冲突解决与恢复)时强制套用安全规则。

作者 Iván533 次安装31 星标

在本地磁盘以分类纯 Markdown 文件保存需要长期留存的事实,与智能体内置记忆并存。

作者 Iván556 次安装18 星标

按配置的 JDK 版本诊断 Java 与 JVM 问题(从 NPE 到容器 OOM),给出可直接套用的代码与配置。

作者 Iván131 次安装9 星标