This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2003年11月10日 11:32 by dcjim, last changed 2022年04月11日 14:56 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| weakrefbug.py | dcjim, 2003年11月10日 11:32 | Script that demonstrates the bug | ||
| weakref_dict_iter.diff | vdupras, 2008年02月24日 14:25 | |||
| Messages (14) | |||
|---|---|---|---|
| msg18959 - (view) | Author: Jim Fulton (dcjim) (Python triager) | Date: 2003年11月10日 11:32 | |
You can't use iterators on wekref dicts because items might be removed from the dictionaries while iterating due to GC. I've attached a script that illustrates the bug with Python 2.3.2. It doesn't matter whether you use weak key or weak value dicts. If this can't be fixed, then the iteration methods should either be removed or made to (lamely) create intermediate lists to work around the problem. |
|||
| msg62908 - (view) | Author: Virgil Dupras (vdupras) (Python triager) | Date: 2008年02月24日 14:25 | |
I made a patch to fix the problem. The cleaning up of they weakref keys or values will be held until all references to iterators created by the weakdict are dead. I also couldn't resist removing code duplication of code in items(), keys() and values(). At first, I couldn't understand why this whole remove(), _remove() and selfref() mechanism was in place. I had removed them and replaced them with methods, and the tests still passed. Then I realized it was to make sure keys and values didn't prevent the weak dicts from being freed. I added tests for this. |
|||
| msg82020 - (view) | Author: Daniel Diniz (ajaksu2) * (Python triager) | Date: 2009年02月14日 12:09 | |
Patch has tests, may need updating. |
|||
| msg82037 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2009年02月14日 12:46 | |
Interesting patch. I think the intermediate assertEquals in test_weak_*_dict_flushed_dead_items_when_iters_go_out are just testing an implementation detail, only the final one should remain. Also, it is likely the "code duplication" you are talking about was there for performance reasons, so I'd suggest putting it back in. |
|||
| msg82062 - (view) | Author: Virgil Dupras (vdupras) (Python triager) | Date: 2009年02月14日 14:11 | |
About duplicated code and performance: When I look at the duplicated code, I don't see anything that remotely looks like a performance tweak. Just to make sure, I made a bench: #!/usr/bin/env python import sys sys.path.insert(0, 'Lib') import timeit import weakref class Foo(object): pass def setup(): L = [Foo() for i in range(1000)] global d d = weakref.WeakValueDictionary(enumerate(L)) del L[:500] # have some dead weakrefs def do(): d.values() print timeit.timeit(do, setup, number=100000) Results without the patch: ./python.exe weakref_bench.py 0.804216861725 Results with the patch: $ ./python.exe weakref_bench.py 0.813000202179 I think the small difference in performance is more attributable to the extra processing the weakref dict does than the deduplication of the code itself. About the test_weak_*_dict_flushed_dead_items_when_iters_go_out: If a weakref dict keeps its weak reference alive, it's not an implementation detail, it's a bug. The whole point of using such dicts is to not keep keys or values alive when they go out. |
|||
| msg82066 - (view) | Author: Virgil Dupras (vdupras) (Python triager) | Date: 2009年02月14日 14:25 | |
Oh, that's me again not correctly reading my own tests. It's the *_are_not_held_* tests that test that no reference is kept. I agree about the *_flushed_dead_items_* being an implementation detail. |
|||
| msg82067 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2009年02月14日 14:28 | |
> Results without the patch: > ./python.exe weakref_bench.py > 0.804216861725 > > Results with the patch: > $ ./python.exe weakref_bench.py > 0.813000202179 Thanks for the numbers, I see my worries were unfounded. > About the test_weak_*_dict_flushed_dead_items_when_iters_go_out: > > If a weakref dict keeps its weak reference alive, it's not an > implementation detail, it's a bug. The whole point of using such dicts > is to not keep keys or values alive when they go out. I was talking about doing `self.assertEqual(len(d), self.COUNT)` before deleting the iterators. |
|||
| msg104842 - (view) | Author: Tres Seaver (tseaver) * | Date: 2010年05月03日 15:08 | |
I can confirm that the patch applies with minimal fuzz to the release26-maint branches and the trunk, and that the added tests fail without the updated implementation in both cases. Furthermore, Jim's original demo script emits it error with my stock 2.6.5 Python, but is silent with the patched trunk / 2.6 branch. |
|||
| msg105159 - (view) | Author: Anthony Lenton (elachuni) * | Date: 2010年05月06日 19:33 | |
Probably old news, but this also affects 2.5.4. |
|||
| msg110338 - (view) | Author: Mark Lawrence (BreamoreBoy) * | Date: 2010年07月14日 22:47 | |
If this is to go forward the patch will need porting to 2.7, 3.1 and 3.2 |
|||
| msg111254 - (view) | Author: Virgil Dupras (vdupras) (Python triager) | Date: 2010年07月23日 09:37 | |
It looks like this issue has been fixed in issue7105 already. Can we close this ticket? |
|||
| msg111256 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2010年07月23日 09:49 | |
It's not yet fixed in 2.7 or 2.6. Updating versions. |
|||
| msg111257 - (view) | Author: Virgil Dupras (vdupras) (Python triager) | Date: 2010年07月23日 09:53 | |
We might as well backport Antoine's patch rather than take this one (even if mine for 2.x already). It would be weird to have 2 wildly different patches to solve the same problem. Maybe close this ticket and flag issue7105 for backporting? |
|||
| msg111258 - (view) | Author: Mark Dickinson (mark.dickinson) * (Python committer) | Date: 2010年07月23日 09:56 | |
Agreed. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:56:01 | admin | set | github: 39529 |
| 2010年07月23日 09:56:04 | mark.dickinson | set | status: open -> closed resolution: duplicate superseder: weak dict iterators are fragile because of unpredictable GC runs messages: + msg111258 |
| 2010年07月23日 09:53:30 | vdupras | set | messages: + msg111257 |
| 2010年07月23日 09:49:15 | mark.dickinson | set | nosy:
+ mark.dickinson messages: + msg111256 versions: + Python 2.6, - Python 3.1, Python 3.2 |
| 2010年07月23日 09:37:48 | vdupras | set | messages: + msg111254 |
| 2010年07月14日 22:47:08 | BreamoreBoy | set | nosy:
+ BreamoreBoy messages: + msg110338 versions: + Python 3.1, Python 2.7, Python 3.2, - Python 2.6, Python 2.5 |
| 2010年05月06日 19:33:37 | elachuni | set | nosy:
+ elachuni messages: + msg105159 versions: + Python 2.5 |
| 2010年05月03日 15:08:36 | tseaver | set | nosy:
+ tseaver messages: + msg104842 |
| 2009年02月14日 14:28:46 | pitrou | set | messages: + msg82067 |
| 2009年02月14日 14:25:07 | vdupras | set | messages: + msg82066 |
| 2009年02月14日 14:11:27 | vdupras | set | messages: + msg82062 |
| 2009年02月14日 12:46:19 | pitrou | set | nosy:
+ pitrou messages: + msg82037 |
| 2009年02月14日 12:09:13 | ajaksu2 | set | nosy:
+ ajaksu2 messages: + msg82020 stage: patch review |
| 2008年02月24日 14:25:37 | vdupras | set | files:
+ weakref_dict_iter.diff versions: + Python 2.6 nosy: + vdupras messages: + msg62908 keywords: + patch type: behavior |
| 2008年02月22日 20:22:21 | akuchling | set | title: interators broken for weak dicts -> iterators broken for weak dicts |
| 2003年11月10日 11:32:12 | dcjim | create | |