-
-
Notifications
You must be signed in to change notification settings - Fork 31.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Isolate the _datetime extension module #117398
Comments
PR #117399 fails except Windows. Is there an easy way to access a |
I briefly discussed the C API capsule with @pganssle on the 2023 (or was it 2022?) language summit. I also asked the Steering Council to comment about backwards compatibility concerns regarding datetime.h (which is not included by Python.h): Putting it in the |
Move types to the datetime_state structure of the _datetime extension.
Move types to the datetime_state structure of the _datetime extension.
Converting the _datetime extension to multiphase initialization and/or converting static types to heap types is complicated because:
It reminds me the very complicated case of the PyAST C API. We managed to convert the _ast extension to heap types and multiphase init by moving state to the interpreter state. Other "trade offs" attemps for the _ast extension ended by introducing crashes which were hard to trigger and hard to fix. So I propose this plan to isolate the datetime module:
|
Where can we see your rationale for the inflating How do you associate the PyAST issue with PyDateTime in terms of the mechanizm and impact? |
Both provide a C API and we wanted to isolate their C extension.
I will try to dig into the bug tracker later. In short, there were 2-3 crashes related to the isolation of the _ast extension. Crashes related to the C API. |
Move types to the datetime_state structure of the _datetime extension.
|
Move types to the datetime_state structure of the _datetime extension.
The purpose of this issue is to convert the _datetime extension to the multiphase C API. The problem is to make sure that we are dealing with the same types if multiple instances of the extension are created. Example: import sys
import _datetime
now = _datetime.datetime.now()
del _datetime
del sys.modules['_datetime']
import _datetime
print(isinstance(now, _datetime.datetime)) In general, we don't require this. For example, it's false with the _random extension: import sys
import _random
rng = _random.Random()
del _random
del sys.modules['_random']
import _random
print(isinstance(rng, _random.Random)) The problem for _datetime is the C API and the capsule. Currently, the C API is based on I would care less if the C API would be stateful: pass explicitly a module/state/something. But changing the C API is out of the scope of this issue. |
The SC said that the datetime C API is protected by PEP-387, even though datetime.h is not explicitly included in Python.h. IMO, we should deprecate the current C API and introduce a new one. That is the easiest solution technically, and the easiest to relate to for users. I agree with Victor that it deserves its own issue (and perhaps also a Discourse topic). |
Move types to the datetime_state structure of the _datetime extension.
I merged my first change "Move types to datetime state". @neonene: Do you want to propose changes to convert static types to heap types? Maybe start with a PR to convert only 4 types to make the PR short enough so it's easier to review. Types:
|
If we manage to isolate the _datetime extension without breaking the C API, I'm not sure that it's needed. |
…ypes (pythongh-119929) We make use of the same mechanism that we use for the static builtin types. This required a few tweaks. The relevant code could use some cleanup but I opted to avoid the significant churn in this change. I'll tackle that separately. This change is the final piece needed to make _datetime support multiple interpreters. I've updated the module slot accordingly. (cherry picked from commit 105f22e) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
…Types (gh-120009) We make use of the same mechanism that we use for the static builtin types. This required a few tweaks. This change is the final piece needed to make _datetime support multiple interpreters. I've updated the module slot accordingly. (cherry picked from commit 105f22e, AKA gh-119929) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
I was able to make use of the existing datetime_state struct, but there was one tricky thing I had to sort out. We mostly aren't converting to heap types, so we can't use things like PyType_GetModuleByDef() to look up the module state. The solution I came up with is somewhat novel, but I consider it straightforward. Also, it shouldn't have much impact on performance. In summary, this main changes here are: * I've added some macros to help hide how various objects relate to module state * as a solution to the module state lookup problem, I've stored the last loaded module on the current interpreter's internal dict (actually a weakref) * if the static type method is used after the module has been deleted, it is reloaded * to avoid extra work when loading the module, we directly copy the objects (new refs only) from the old module state into the new state if the old module hasn't been deleted yet * during module init we set various objects on the static types' __dict__s; to simplify things, we only do that the first time; once those static types have a separate __dict__ per interpreter, we'll do it every time * we now clear the module state when the module is destroyed (before, we were leaking everything in _datetime_global_state)
…ypes (pythongh-119929) We make use of the same mechanism that we use for the static builtin types. This required a few tweaks. The relevant code could use some cleanup but I opted to avoid the significant churn in this change. I'll tackle that separately. This change is the final piece needed to make _datetime support multiple interpreters. I've updated the module slot accordingly.
…-119604) Check if the DateTime C-API type matches the datetime.date type on main and shared/isolated subinterpreters.
…rs (pythongh-119604) Check if the DateTime C-API type matches the datetime.date type on main and shared/isolated subinterpreters. (cherry picked from commit 50a3895) Co-authored-by: neonene <53406459+neonene@users.noreply.github.com>
…t. (#120477) Use the correct loader for iOS.
…rs (pythongh-119604) Check if the DateTime C-API type matches the datetime.date type on main and shared/isolated subinterpreters.
…PI test. (python#120477) Use the correct loader for iOS.
…hongh-119637) This is the only static type in the module that we will not keep static.
I was able to make use of the existing datetime_state struct, but there was one tricky thing I had to sort out. We mostly aren't converting to heap types, so we can't use things like PyType_GetModuleByDef() to look up the module state. The solution I came up with is somewhat novel, but I consider it straightforward. Also, it shouldn't have much impact on performance. In summary, this main changes here are: * I've added some macros to help hide how various objects relate to module state * as a solution to the module state lookup problem, I've stored the last loaded module on the current interpreter's internal dict (actually a weakref) * if the static type method is used after the module has been deleted, it is reloaded * to avoid extra work when loading the module, we directly copy the objects (new refs only) from the old module state into the new state if the old module hasn't been deleted yet * during module init we set various objects on the static types' __dict__s; to simplify things, we only do that the first time; once those static types have a separate __dict__ per interpreter, we'll do it every time * we now clear the module state when the module is destroyed (before, we were leaking everything in _datetime_global_state)
…ypes (pythongh-119929) We make use of the same mechanism that we use for the static builtin types. This required a few tweaks. The relevant code could use some cleanup but I opted to avoid the significant churn in this change. I'll tackle that separately. This change is the final piece needed to make _datetime support multiple interpreters. I've updated the module slot accordingly.
…rs (pythongh-119604) Check if the DateTime C-API type matches the datetime.date type on main and shared/isolated subinterpreters.
…PI test. (python#120477) Use the correct loader for iOS.
This is minimal support. Subinterpreters are not supported yet. That will be addressed in a later change. Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
…don't free it (pythonGH-119662) - While datetime uses global state, only initialize it once. - While `capi` is static, don't free it (thanks @neonene in https://github.com/python/cpython/pull/119641/files#r1616710048)
…hongh-119637) This is the only static type in the module that we will not keep static.
I was able to make use of the existing datetime_state struct, but there was one tricky thing I had to sort out. We mostly aren't converting to heap types, so we can't use things like PyType_GetModuleByDef() to look up the module state. The solution I came up with is somewhat novel, but I consider it straightforward. Also, it shouldn't have much impact on performance. In summary, this main changes here are: * I've added some macros to help hide how various objects relate to module state * as a solution to the module state lookup problem, I've stored the last loaded module on the current interpreter's internal dict (actually a weakref) * if the static type method is used after the module has been deleted, it is reloaded * to avoid extra work when loading the module, we directly copy the objects (new refs only) from the old module state into the new state if the old module hasn't been deleted yet * during module init we set various objects on the static types' __dict__s; to simplify things, we only do that the first time; once those static types have a separate __dict__ per interpreter, we'll do it every time * we now clear the module state when the module is destroyed (before, we were leaking everything in _datetime_global_state)
…ypes (pythongh-119929) We make use of the same mechanism that we use for the static builtin types. This required a few tweaks. The relevant code could use some cleanup but I opted to avoid the significant churn in this change. I'll tackle that separately. This change is the final piece needed to make _datetime support multiple interpreters. I've updated the module slot accordingly.
…rs (pythongh-119604) Check if the DateTime C-API type matches the datetime.date type on main and shared/isolated subinterpreters.
…PI test. (python#120477) Use the correct loader for iOS.
Feature or enhancement
Proposal:
I hope this issue will complete
_datetime
isolation.My concerns (and answers)
Py_MOD_PER_INTERPRETER_GIL_SUPPORTED
should be applied in sync with_zoninfo
?Can a module state have a C-API structure, keeping a capsule just for comatibility?
C-API supports only the main interpreter? Otherwise,
PyInterpreterState
is acceptable to point each structure?PyDateTimeAPI
cannot emit an error. Also, noPyInterpreterState
member is accessible fromdatetime.h
. UPDATE: Seems to be possible by using a global function pointer instead of a function.Specific issue:
Links to previous discussion of this feature:
_datetime
#102995_datetime
#110475Linked PRs (closed)
PyInterpreterState
#118357Linked PRs
_strptime
module in_datetime
#120224The text was updated successfully, but these errors were encountered: