msg43002 - (view) |
Author: Walter Dörwald (doerwalter) *  |
Date: 2003-03-11 18:59 |
Python allows to put something that is not a module in sys.modules. Unfortunately reload() does not work wth such a pseudo module ("TypeError: reload() argument must be module" is raised). This patch changes Python/import.c::PyImport_ReloadModule() so that it works with anything that has a __name__ attribute that can be found in sys.modules.keys(). |
|
|
msg43003 - (view) |
Author: Martin v. Löwis (loewis) *  |
Date: 2003-03-15 13:51 |
Logged In: YES user_id=21627 I think the exceptions need to be reworked: "must be a module" now only occurs if m is NULL. Under what circumstances could that happen? Failure to provide __name__ is passed through; shouldn't this get diagnosed in a better way? |
|
|
msg43004 - (view) |
Author: Walter Dörwald (doerwalter) *  |
Date: 2003-03-17 14:25 |
Logged In: YES user_id=89016 PyImport_ReloadModule() is only called by the implementation of the reload builtin, so it seems that m==NULL can only happen with broken extension modules. I've updated the patch accordingly (raising a SystemError) and changed the error case for a missing __name__ attribute to raise a TypeError when an AttributeError is detected. Unfortunately this might mask exceptions (e.g. when __name__ is implemented as a property.) Another problem is that reload() seems to repopulate the existing module object when reloading real modules. Example: Write a simple foo.py which contains "x = 1" and then: >>> import foo >>> foo.x 1 [ Now open your editor and change foo.py to "x = 2" ] >>> foo2 = reload(foo) >>> foo.x 2 >>> foo2.x 2 >>> print id(foo), id(foo2) 1077466884 1077466884 >>> Of course this can't work with pseudo modules. I wonder why reload() has a return value at all, as it always modifies its parameter for real modules. |
|
|
msg43005 - (view) |
Author: Martin v. Löwis (loewis) *  |
Date: 2003-03-30 16:34 |
Logged In: YES user_id=21627 The patch looks fine now as far as it goes. I'm unsure what the use case is, though: What object do you have in sys.modules for which reload() would be meaningful? Can you attach an example where reloading fails now but succeeds with your patch applied? As for reload modifying the module object: It needs to, or else all clients would have to run reload; this would include things like function default arguments. I guess it returns a result for historical reasons. |
|
|
msg43006 - (view) |
Author: Walter Dörwald (doerwalter) *  |
Date: 2003-03-31 19:38 |
Logged In: YES user_id=89016 A use case can be found at http://www.livinglogic.de/viewcvs/index.cgi/LivingLogic/xist/_xist/xsc.py?rev=2.235 (Look for the classmethod makemod() in the class Namespace). This puts a class object into sys.modules instead of the module that defines this class. This makes it possible to derive from "modules". Of course the patch does not fully fix the problem, because reload() does not repopulate the class object. Unfortunately that's impossible to fix with Python code, as it's impossible for Python code to distinguish the first import from subsequent ones. If this was possible (and Python code had access to the old "module"), a real reload could be coded in pure Python for this specific case. But with the patch at least it's possible to use the return value of reload() afterwards to use the new "module". |
|
|
msg43007 - (view) |
Author: Martin v. Löwis (loewis) *  |
Date: 2007-03-13 09:29 |
I have now updated the patch to the current trunk, however, I fail to see how it fixes the bug. See the included test case: it reports an ImportError on the reload, saying that there is no module named 'fake'. File Added: diff3.txt |
|
|
msg43008 - (view) |
Author: Walter Dörwald (doerwalter) *  |
Date: 2007-03-13 17:55 |
This patch only works if there's a real module behind the fake one, i.e. if the imported module replaces itself if sys.modules. To test, put the following into fake.py: --- class FakeMod: def __init__(self, n): self.__name__ = n def foo(self): return 42 import sys sys.modules[__name__] = FakeMod(__name__) --- On the commandline do: >>> import fake >>> import sys >>> fake <fake.FakeMod instance at 0xb77bdea4> >>> fake.foo() 42 [Now edit fake.py and change 42 to 43] >>> fake2 = reload(fake) >>> fake2 <fake.FakeMod instance at 0xb77bdaec> >>> fake.foo() 42 >>> fake2.foo() 43 >>> sys.modules['fake'].foo() However I'm no longer sure that the patch in this form is all that useful. |
|
|
msg68585 - (view) |
Author: Facundo Batista (facundobatista) *  |
Date: 2008-06-22 22:07 |
Walter, the import mechanisms changed by a big rework from Brett Cannon in the last months. Do you think still have a use case that should be fulfilled? Do you want to update your patch? Thank you! |
|
|
msg68616 - (view) |
Author: Walter Dörwald (doerwalter) *  |
Date: 2008-06-23 08:50 |
AFAIK reload() is gone in 3.0 anyway, so I don't think this patch is relevant any longer. |
|
|
msg85146 - (view) |
Author: Brett Cannon (brett.cannon) *  |
Date: 2009-04-02 02:53 |
Since reload is about reloading modules and sticking stuff other than modules in sys.modules is a partial hack I am closing as "rejected". |
|
|