Python开发中的小问题及解决方法

Python开发中的小问题及解决方法
青夢Python开发中的小问题及解决方法
Pycharm不以pytest方式运行
运行脚本的时候以pytest方式运行时,如果要换回普通模式
- 点击运行脚本时的配置旁边的展开
- 点击
Edit configurations - 删除原有的pytest运行配置
- 新增Python运行配置
- 填写运行配置Name
- 配置python解释器路径
- 配置要运行的脚本路径
- 保存即可以普通模式运行
解决urllib.request的HTTP请求在开启代理的情况下,访问502
问题背景:在开启Clash Verge系统代理,且是规则模式,已对访问域名及ip(这里是内网搭建的服务)尝试添加规则,会遇到错误
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。;但是关闭系统代理后,就能正常执行,目标的域名和ip也能ping的通。
ping的痛验证的是ICMP协议的连通性,并不代表HTTP请求会走同样的路径,系统代理主要影响的是HTTP/HTTPS流量。这个问题是由于urllib.request默认从环境变量或Windows注册表中获取代理设置,这可能回导致请求被代理拦截或路由错误。
由于这里的服务属于内网服务,即使Clash规则设定该域名为直连,开启系统代理后,请求经过代理的服务器无法访问到内网的服务而导致问题的出现。
方法一:
运行脚本前为访问的域名或ip设置环境变量
1
2
3set NO_PROXY=<域名>,<内网服务ip>
例子:set NO_PROXY=030321.xyz,10.10.11.*Pycharm中编辑环境配置,在环境变量中添加
NO_PROXY,值同上
方法二:
代码中添加
1
2
3
4
5
6
7
8
9import os
os.environ["no_proxy"] = "<域名>,<内网服务ip>"
# 或者
import urllib.request
opener = urllib.request.build_opener(urllib.request.ProxyHandler({})) # 传空字典关闭代理
urllib.request.install_opener(opener)
# 然后再调用 push_to_gateway,这时 urllib 会使用没有代理的新 opener。
双下划线导致名称重整问题
在 Python 中,类中以 __ 开头但不以 __ 结尾的方法或属性会被“名称重整”(name mangling),以防止子类覆盖或外部访问。如
1 | class BotConfigLoader: |
会被编译为
1 | _BotConfigLoader__replace_variable |
而就会可能遇到(情况:只在一台pc上遇到,其他的没有遇到,但是清理__pycache__缓存后又可以正常调用)
1 | BotConfigLoader.__replace_variable(...) |
解决方案
将方法名改为
_replace_variable,表示“受保护”但不会触发名称重整使用类名重整后的名称调用;不推荐
1
BotConfigLoader._BotConfigLoader__replace_variable(input_str, params_dict)
拓展
使用单下划线
_method表示“内部使用”,但不触发名称重整;双下划线__method仅用于防止子类覆盖或外部访问,适用于类属性而非工具方法;如果希望方法完全私有,考虑将其移入闭包或模块级私有函数彻底清理
__pycache__缓存项目根目录执行,递归删除所有
__pycache__文件夹1
2
3
4
5
6
7# Linux / macOS
find . -type d -name "__pycache__" -exec rm -rf {} +
# Windows PowerShell
cd "D:\MyProject" # 路径有空格需加引号
Get-ChildItem -Path . -Recurse -Directory -Filter "__pycache__" | Remove-Item -Recurse -Force防止以后生成,设置环境变量(建议只在调试或临时环境用,
.pyc有助于提高加载速度)1
2
3
4
5# Linux / macOS
export PYTHONDONTWRITEBYTECODE=1
# Windows PowerShell
setx PYTHONDONTWRITEBYTECODE 1
python -m http.server访问编码问题
情景:python -m http.server 启动的 HTTP 服务默认会以 ISO-8859-1(Latin-1)编码 来处理静态文件,而不是 UTF-8。导致在浏览器中访问 .js 文件时,中文字符被错误地解析为乱码。实际上使用vscode保存为UTF-8也没有正常加载。
解决方法:使用Node.js的http-server
1 | npm install -g http-server |
命令行临时设置代理
把HTTP/HTTPS 请求走本机代理软件的本地端口,临时生效,关掉窗口就会失效
1 | # 临时生效 |
在类体内使用 @property + @classmethod 的组合在3.11弃用/3.13移除
1 | class TestTriggerCls: |
property 期待的是一个“实例方法”,结果却收到了一个 classmethod 对象,classmethod 不是普通函数,它不能直接调用,导致属性机制没法正常工作。
在 Python 里,property 是一个 描述符类,用来把方法变成属性。
它的构造方法是:
1 | property(fget=None, fset=None, fdel=None, doc=None) |
fget:获取属性时调用的函数(getter)。fset:给属性赋值时调用的函数(setter)。fdel:删除属性时调用的函数(deleter)。doc:属性的文档字符串。
uv启动jupyter并设置中文
1 | uv pip install jupyterlab-language-pack-zh-CN |
random.choices()随机出现重复元素
这是因为random.choices()的行为是有放回地随机抽取元素,当从列表 l = [1, 2] 中用 random.choices(l, k=2) 抽取两个元素时:
- 每次抽取后,元素会“放回”列表中,下一次抽取仍然可能抽到同一个元素。
- 所以
[1, 1]、[2, 2]、[1, 2]、[2, 1]都是可能的结果。
避免重复可以使用``random.sample(),这是无放回抽取
Mock配置类
Mock(模拟)是一种测试技术,它用一个虚拟的对象(称为Mock 对象)来代替真实对象,能够被开发者控制。
1 | # 支持空字典和空可迭代对象的一个Mock配置类 |
Python关键字
| 分类 | 关键字 | 作用简述 |
|---|---|---|
| 逻辑与布尔 | True, False, None |
布尔值和空值 |
| 条件与循环 | if, elif, else, for, while, break, continue |
条件控制与循环控制 |
| 函数与类 | def, class, lambda, return, yield |
定义函数/类,返回值,生成器 |
| 作用域 | global, nonlocal |
作用域声明 |
| 异常处理 | try, except, finally, raise, assert |
异常捕获、抛出、断言 |
| 导入与模块 | import, from, as |
模块导入与别名 |
| 上下文管理 | with |
上下文管理器(常配合 open) |
| 运算相关 | and, or, not, is, in |
逻辑与/或/非,身份运算,成员运算 |
| 异步与并发 | async, await |
协程与异步编程 |
| 其他语法 | pass, del, match, case |
占位、删除、结构化模式匹配(3.10+ 引入) |
可以打印输出内置库中的对象获取使用的Python版本中包含的关键字
1 | import keyword |
global和nonlocal的区别:global指向的是全局变量,而nonlocal指向的是外层函数的局部变量。global可以在任何地方使用,而nonlocal只能在嵌套函数的内层使用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30# 全局变量
global_var = 1
def func1():
global global_var
global_var += 1
func1()
print(global_var) # 输出2
# 局部变量
def func1():
var1 = 'a'
def func2():
nonlocal var1
var1 += 'b'
func2()
print(var1) # 输出ab
func1()
# 注意:上面的局部变量部分代码并不是闭包,闭包要满足三个条件,1、嵌套函数:存在一个内部函数嵌套在外部函数中2、引用外部作用域变量:内部函数引用了其外部作用域中的变量,并且这个引用在外部函数执行完毕后依然存在。3、外部函数返回了内部函数
# 闭包函数
def func1():
var1 = 'a'
def func2():
nonlocal var1
var1 += 'b'
return var1
return func2
f = func1()
print(f()) # 输出ab
print(f()) # 输出abb
Git 和 SVN 在提交大量小文件修改的性能差异
在使用SVN提交合并大量小文件配置修改时(1~2k)时发现很容易出现网络出错,且处理速度很慢。
| 特性 | Git | SVN |
|---|---|---|
| 提交位置 | 本地先提交,再推送远程 | 直接提交到远程服务器 |
| 网络依赖 | 低(本地操作快) | 高(每次提交都依赖网络) |
| 并发提交处理 | 支持本地分支并行提交 | 容易冲突,需排队提交 |
| 文件存储方式 | 快照(压缩优化) | 差异增量存储 |
这是由于SVN每次提交都需要连接远程仓库,每个文件都要逐个处理差异,过程就会很慢,文件数量巨大的时候,.svn元素据目录也会膨胀,影响性能;但是SVN在处理大文件或二进制文件时更稳定。最后是分批进行多次提交合并解决
而Git是本地提交,几乎不受文件数量影响,使用快照机制,跳过未变更文件,避免重复存储,在处理大量小文件时,提交速度更快。
Python各版本性能差异
从3.7开始,持续使用Cpython进行大量底层改进,性能逐步提升,并且是首次超越2.7;在3.11引入了Adaptive Interpreter(PEP 659)和更多执行效率优化,是性能提升最大的一次;在3.13及以上,支持JIT 和 Free-threading。
Adaptive Interpreter(自适应解释器):观察你的程序,针对常用操作生成优化执行策略
1
2
3
4
5
6
7
8# 假设频繁访问对象属性
class Person:
def __init__(self, name):
self.name = name
p = Person("Alice")
for _ in range(10_000_000):
x = p.name # 热路径操作普通解释器:每次访问都要查找字典、检查类型 → 较慢
Adaptive Interpreter:检测到
p.name是热点 → 生成专用快速指令 → 直接取值 → 快很多JIT(Just-In-Time 编译、即时编译器):在程序运行时把某些代码片段从字节码(interpreter 执行)编译成机器码(CPU 可直接执行)
1
2
3
4# 热循环
total = 0
for i in range(100_000_000):
total += i普通解释器:每次循环都解释执行字节码 → 慢
JIT 编译后:整个循环生成机器码 → CPU 可以直接执行 → 快很多
Free-threading:
Python 的 GIL(Global Interpreter Lock,全局解释器锁)会限制同一时刻只有一个线程在执行 Python 字节码,导致多线程无法充分利用多核 CPU
1
2
3
4
5
6
7
8import threading
def compute():
sum(i*i for i in range(10**7))
threads = [threading.Thread(target=compute) for _ in range(4)]
[t.start() for t in threads]
[t.join() for t in threads]普通 CPython(有 GIL):四个线程依然几乎串行执行
Free-threading 版本:四个线程可并行执行 → 利用四核 CPU → 速度大幅提升
Git不追踪文件名的大小写变化的问题
Git 在某些操作系统(尤其是 macOS 和 Windows)上默认不追踪文件名的大小写变化,这是因为这些系统的文件系统是大小写不敏感的(case-insensitive)。这会导致在本地修改了文件名的大小写,但 Git 并不会认为这是一次变更,从而不会提交到远程仓库。
场景:hexo将python爬虫基础.md重命名成Python爬虫基础.md,提交到远程仓库成功,但是访问重命名后的路径是404,这是由于在 macOS 或 Windows 上,Git 可能会认为这两个文件是一样的,不会记录这个改名操作。结果就是:
- 本地预览没问题
- 部署到 Linux 环境(如 Cloudflare Pages)时,路径大小写敏感,导致找不到文件 → 404
解决方法:将文件内容复制到temp.md,删除原文件并提交和推送,重新修改回原来的文件再次提交即可,Git就会识别出并更新,
可选解决方法(不推荐):全局配置,
git config core.ignorecase false
Git的变更判断分类
| 类型 | Git 判断方式 | 是否受文件系统影响 |
|---|---|---|
| 内容变更 | 通过 SHA-1 哈希对比内容快照 | 否 |
| 文件名变更 | 通过文件路径对比(包括大小写) | 是(尤其大小写) |
Git 是通过内容快照和哈希值来判断文件内容是否变更,但文件名的变更(尤其是大小写)属于元数据变更,Git 的处理方式会受到操作系统文件系统的影响。
为什么大小写变化可能会被忽略
在 大小写不敏感的文件系统(如 macOS 默认的 HFS+,Windows 的 NTFS)中:
file.md和File.md被认为是同一个文件- Git 的默认配置
core.ignorecase = true,会忽略大小写变化 - 所以改了文件名大小写,Git 不会认为这是一次变更 → 不会记录 → 不会提交 → 不会部署












