StripeError exceptions are not pickleable
维护者通常 2 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 55/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- python
调研方向
Start by locating StripeError and its subclasses, especially InvalidRequestError, and read how their constructors and exception arguments are handled. Reproduce the pickle round trip in the issue with Python 3.12, then inspect or add tests for serializing and deserializing the error. Done means the round trip succeeds for InvalidRequestError and its required fields are preserved.
由索引模型根据 Issue 内容生成。
描述
Describe the bug
StripeError exceptions can't be serialized and deserialized using pickle.
We use Celery and the errors returned by Stripe API calls can't be serialized and can't be caught outside of the async task.
To Reproduce
from stripe import StripeClient, InvalidRequestError
import pickle
try:
StripeClient("myapikey").v1.prices.list({"expand": ["notexpandable"]})
except InvalidRequestError as e:
pickle.loads(pickle.dumps(e)) # TypeError: InvalidRequestError.__init__() missing 1 required positional argument: 'param'
Expected behavior
InvalidRequestError can pickled:
pickle.loads(pickle.dumps(e))
raises no error
Code snippets
OS
Linux
Language version
Python 3.12
Library version
stripe-python v15.6.1
API version
2026-02-25.clover
Additional context
I suggest to not call the super().__init__() of the StripeError class. When the exception is pickled, it is deconstructed and reconstructed using the exc.args attribute, only the arguments passed to the parent class will be included in exc.args. For example:
class StripeError(Exception):
def __init__(message, http_body, http_status):
super().__init__(message)
....
StripeError("message", {"response": "body"}, 400).args # ("message",) all other arguments are not included
Solution:
class StripeError(Exception):
def __init__(message, http_body, http_status):
# do not call __init__ of Exception
....
StripeError("message", {"response": "body"}, 400).args # ("message", {"response": "body"}, 400)
But still if we pass keyword arguments:
class StripeError(Exception):
def __init__(message, http_body, http_status):
# do not call __init__ of Exception
....
# keyword arguments are not include in exception args
StripeError("message", http_body={"response": "body"}, status=400).args # ("message",)
We could think of passing all parameters to the parent class, but:
class StripeError(Exception):
def __init__(message, http_body, http_status):
# pass all parameters to parent class
super().__init__(message, http_body, http_status)
# instances of StripeError are fixed
StripeError("message", http_body={"response": "body"}, status=400).args # ("message", {"response": "body"}, 400)
# but what if we subclass again?
class InvalidRequesError(StripeError):
def __init__(message, http_body, http_status, param):
# pass all parameters to parent class
super().__init__(message, http_body, http_status)
self.param = param
# now we have an issue again
InvalidRequesError("message", {"response": "body"}, 400, "param").args # ("message", {"response": "body"}, 400) param is missing
One possible solution, never call Exception.init() and accept *args which will be forwarded to the parent class:
class StripeError(Exception):
# accept *args
def __init__(message, http_body, http_status, *args):
# do not call Exception.__init__()
...
# instances of StripeError are fixed
StripeError("message", {"response": "body"}, 400).args # ("message", {"response": "body"}, 400)
class InvalidRequesError(StripeError):
def __init__(message, http_body, http_status, param):
# pass all parameters to parent class
super().__init__(message, http_body, http_status, param)
self.param = param
# now also subclasses are fixed
InvalidRequesError("message", {"response": "body"}, 400, "param").args # ("message", {"response": "body"}, 400, "param")
If we want to subclass InvalidRequestError it will also have to accept *args and forward everything as positional argument to its parent class.
- 主要语言
- Python
- 星标
- 2.1k
- 派生
- 538
- 平均合并
- 2 天 16 小时
- 30 天内合并 PR
- 28
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
stripe/stripe-python 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 78/100
stripe/stripe-python#1936 · 2 条评论 ·
维护者通常 2 天内回复
-
feature-request future
难度 4/5 3-5 天 新手友好度 35/100
stripe/stripe-python#1886 · 1 条评论 ·
维护者通常 2 天内回复
-
feature-request
难度 2/5 1-3 小时 新手友好度 54/100
stripe/stripe-python#1841 · 1 条评论 ·
维护者通常 2 天内回复
-
feature-request future
难度 3/5 1-2 天 新手友好度 52/100
stripe/stripe-python#1812 · 1 条评论 ·
维护者通常 2 天内回复
-
Add async context manager support for AIOHTTPClient and HTTPXClient可能重新可做 关联的 PR 已关闭且未合并。 未关闭feature-request future
难度 3/5 1-2 天 新手友好度 74/100
stripe/stripe-python#1796 · 3 条评论 ·
维护者通常 2 天内回复
查看 stripe/stripe-python 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 68/100
pyjanitor-devs/pyjanitor#1758 ·
维护者通常 1 天内回复
-
bug ready for review
难度 2/5 1-3 小时 新手友好度 86/100
odysseus-dev/odysseus#6641 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 76/100
happypawspillaro/happypaws#78 ·
维护者通常 4 天内回复
-
pydanty:is-working
难度 2/5 1-3 小时 新手友好度 82/100
pydantic/pydantic-ai#10020 ·
维护者通常 1 天内回复
-
stdlib type-bug
难度 2/5 1-3 小时 新手友好度 68/100
python/cpython#159044 · 4 条评论 ·
维护者通常 1 天内回复