Issue12920
Created on 2011-09-06 18:37 by Claudiu.Popa, last changed 2022-04-11 14:57 by admin.
| Messages (15) | |||
|---|---|---|---|
| msg143645 - (view) | Author: PCManticore (Claudiu.Popa) * ![]() |
Date: 2011-09-06 18:37 | |
inspect.getsource called with a class defined in the same file fails with TypeError: <module '__main__' (built-in)> is a built-in class, although the documentation says that: "The argument may be a module, class, method, function, traceback, frame, or code object. The source code is returned as a single string." I think that should be specified in documentation that this function works only for objects living in a module. |
|||
| msg143773 - (view) | Author: Éric Araujo (eric.araujo) * ![]() |
Date: 2011-09-09 17:16 | |
> inspect.getsource called with a class defined in the same file fails > with TypeError: <module '__main__' (built-in)> is a built-in class The error message makes me think that getsource(__main__) was used, not getsource(SomeClass). Can you check again? |
|||
| msg143790 - (view) | Author: PCManticore (Claudiu.Popa) * ![]() |
Date: 2011-09-09 18:59 | |
Yes. On Python 3.2 (r32:88445, Feb 20 2011, 21:29:02) [MSC v.1500 32 bit (Intel)] on win32, the result for the following lines:
import inspect
class A:
pass
inspect.getsource(A)
is:
Traceback (most recent call last):
File "E:/Scripts/Snippets/test_inspect_bug.py", line 4, in <module>
inspect.getsource(A)
File "C:\Python32\lib\inspect.py", line 694, in getsource
lines, lnum = getsourcelines(object)
File "C:\Python32\lib\inspect.py", line 683, in getsourcelines
lines, lnum = findsource(object)
File "C:\Python32\lib\inspect.py", line 522, in findsource
file = getsourcefile(object)
File "C:\Python32\lib\inspect.py", line 441, in getsourcefile
filename = getfile(object)
File "C:\Python32\lib\inspect.py", line 406, in getfile
raise TypeError('{!r} is a built-in class'.format(object))
TypeError: <module '__main__' (built-in)> is a built-in class
>>>
|
|||
| msg143831 - (view) | Author: PCManticore (Claudiu.Popa) * ![]() |
Date: 2011-09-10 06:45 | |
I forgot to mention that I executed this code directly in IDLE. It seems to work perfectly on command line though. |
|||
| msg185179 - (view) | Author: Éric Araujo (eric.araujo) * ![]() |
Date: 2013-03-25 02:54 | |
> It seems to work perfectly on command line though. If the code is saved in a file, yes, but not in an interactive interpreter. This is not actually related to IDLE, but to the fact that inspect.getsource merely finds the __file__ attribute of the module object for its argument. If a module object has no file, the error message indicates that it’s a built-in module (like sys), but this fails to take into account the special __main__ module in an interactive interpreter. It might be worth it to improve the error message, and in any case the documentation can be improved. |
|||
| msg245714 - (view) | Author: Ned Deily (ned.deily) * ![]() |
Date: 2015-06-24 04:04 | |
In duplicate Issue24491, zorceta notes: "Both python.exe and IDLE can't. IPython is able to, as it inserts REPL input into linecache." |
|||
| msg245721 - (view) | Author: Zorceta (zorceta) | Date: 2015-06-24 05:45 | |
When provided object is not from a file, like input in interactive shell, `inspect` internals will check for it in `linecache`, which official Python shell and IDLE won't put interactive shell input into, yet. This can be simply solved. Whether interactive shell input can be put into `linecache` may be a problem, but it'll make life easier, as interactive shell saves time from edit-save-run 'loop'. btw, I changed the title, since I don't think, what original author thought need to be documented, is absolutely right. |
|||
| msg245723 - (view) | Author: Zorceta (zorceta) | Date: 2015-06-24 06:05 | |
> When provided object is not from a file should be 'When `inspect` can't find the source file of provided object'. My mistake. |
|||
| msg252846 - (view) | Author: (nikitakit) | Date: 2015-10-12 06:33 | |
I just ran into this issue trying to introspect an IPython session, in which case the __main__ module doesn't have a file associated with it. But it turns out that methods defined in a class do have source code associated with them, so it's possible to add a workaround for the common case where a class actually has methods. Code: https://gist.github.com/nikitakit/642cb96febdf2f812d0b |
|||
| msg265815 - (view) | Author: Steven Barker (Steven.Barker) * | Date: 2016-05-18 06:45 | |
The problem being discussed here just came up on Stack Overflow today: http://stackoverflow.com/questions/37288135/inspect-module-for-python/ The cause of the incorrect error message is pretty clear. The relevant code from `inspect.getfile` should do something better when the object has a `__module__` attribute, but the module named (when looked up in `sys.modules`) does not have a `__file__` attribute. Currently it says the module is a builtin class, which is total nonsense. A very basic fix would be to have an extra error case: if isclass(object): if hasattr(object, '__module__'): object = sys.modules.get(object.__module__) if hasattr(object, '__file__'): return object.__file__ raise TypeError() # need a relevant message here!!! raise TypeError('{!r} is a built-in class'.format(object)) It might be easier to make a meaningful message if the code after the first `if` didn't overwrite `object` with the module. But, really, it would be nice to figure out a better fix, which would make the relevant inspect functions actually work for classes defined interactively in the `__main__` module. |
|||
| msg297768 - (view) | Author: Vitor Pereira (vmsp) * | Date: 2017-07-05 15:25 | |
So, what would be the right approach here? Store the interactive session's input text in memory? |
|||
| msg297797 - (view) | Author: R. David Murray (r.david.murray) * ![]() |
Date: 2017-07-06 04:04 | |
Probably. Figure out a protocol to inject them into linecache, perhaps. But I'm not sure such a thing would be accepted. If you can figure out a way to make it work at least theoretically, it would probably be best to talk about it on python-ideas first. In the meantime it would be nice to improve the error message, which is what we should use this issue for. |
|||
| msg328836 - (view) | Author: Ivan Pozdeev (Ivan.Pozdeev) * | Date: 2018-10-29 15:02 | |
See https://bugs.python.org/issue33826?@ok_message=msg%20328824%20created%0Aissue%2033826%20message_count%2C%20messages%20edited%20ok&@template=item#msg319692 how IPython stores source from interactive input and why it's not appropriate for vanilla REPL IMO. |
|||
| msg331659 - (view) | Author: Terry J. Reedy (terry.reedy) * ![]() |
Date: 2018-12-11 22:23 | |
Do we really need to say that getsource(object) can only get the object's source if it is accessible from the object? Getsource also fails if a module is loaded from a .pyc with not corresponding .py available.
The problem is not the call being in __main__. When I put the three lines (with the 3rd wrapped with print()) in an IDLE editor and run, and re-inspect, I get
======================== RESTART: F:\Python\a\tem3.py ========================
class A:
pass
>>> inspect.getsource(A)
'class A:\n pass\n'
Ditto if I run > py -i -m a.tem3
If I continue in IDLE's Shell
>>> class B: pass
>>> inspect.getsource(B)
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
inspect.getsource(B)
File "F:\dev\37\lib\inspect.py", line 973, in getsource
lines, lnum = getsourcelines(object)
File "F:\dev\37\lib\inspect.py", line 955, in getsourcelines
lines, lnum = findsource(object)
File "F:\dev\37\lib\inspect.py", line 812, in findsource
raise OSError('could not find class definition')
OSError: could not find class definition
If I enter the three lines above in a fress python or IDLEs shell, I get the TypeError above.
IDLE does store interactive inputs into linecache, so that tracebacks contain the offending line (unlike interactive python). But it does so on a statement by statement basis, so that each entry is treated as a separate file. In a traceback for an exception in a multiline statement, the line number is relative to the statement.
>>> def f():
# line2 of f
1/0
>>> f()
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
f()
File "<pyshell#12>", line 3, in f
1/0
ZeroDivisionError: division by zero
Interactive python displays '<stdin>' as the file for all entries. IDLE numbers them, so previous statements remained cached. I consider enhanced interactive tracebacks to be an important feature.
But I don't see how to attach individual pseudofile names to classes and functions so that getsource could find their source lines.
|
|||
| msg382107 - (view) | Author: Alexey Volkov (Ark-kun) | Date: 2020-11-30 02:13 | |
This is also an issue even for non-interactive scenarios: When doing `python -c '<some code>'` inspect.getsource does not work and there are no stack traces. Perhaps this case will be easier to fix? |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:57:21 | admin | set | github: 57129 |
| 2020-11-30 02:13:01 | Ark-kun | set | nosy:
+ Ark-kun messages: + msg382107 |
| 2018-12-11 22:23:06 | terry.reedy | set | nosy:
+ terry.reedy messages:
+ msg331659 |
| 2018-10-29 15:02:29 | Ivan.Pozdeev | set | nosy:
+ Ivan.Pozdeev messages: + msg328836 |
| 2017-07-06 04:04:18 | r.david.murray | set | nosy:
+ r.david.murray messages: + msg297797 |
| 2017-07-05 15:25:22 | vmsp | set | nosy:
+ vmsp messages: + msg297768 |
| 2016-05-18 06:45:42 | Steven.Barker | set | nosy:
+ Steven.Barker messages: + msg265815 |
| 2015-10-12 06:33:34 | nikitakit | set | nosy:
+ nikitakit messages: + msg252846 |
| 2015-06-24 06:05:03 | zorceta | set | messages: + msg245723 |
| 2015-06-24 05:46:58 | zorceta | set | nosy:
- docs@python |
| 2015-06-24 05:46:38 | zorceta | set | components: + IDLE, Interpreter Core, - Documentation |
| 2015-06-24 05:45:05 | zorceta | set | messages:
+ msg245721 title: Document that inspect.getsource only works for objects loaded from files, not interactive session -> inspect.getsource only works for objects loaded from files, not interactive session |
| 2015-06-24 04:04:41 | ned.deily | link | issue24491 superseder |
| 2015-06-24 04:04:29 | ned.deily | set | nosy:
+ ned.deily, zorceta messages:
+ msg245714 |
| 2013-03-25 02:54:47 | eric.araujo | set | title: inspect.getsource fails to get source of local classes -> Document that inspect.getsource only works for objects loaded from files, not interactive session stage: needs patch messages: + msg185179 versions: + Python 3.4 |
| 2013-03-24 00:40:58 | Naddiseo | set | nosy:
+ Naddiseo |
| 2011-09-10 06:45:37 | Claudiu.Popa | set | messages: + msg143831 |
| 2011-09-09 18:59:58 | Claudiu.Popa | set | messages: + msg143790 |
| 2011-09-09 17:16:18 | eric.araujo | set | nosy:
+ eric.araujo title: Inspect.getsource fails to get source of local classes -> inspect.getsource fails to get source of local classes messages: + msg143773 versions: - Python 3.1 |
| 2011-09-06 18:37:57 | Claudiu.Popa | create | |

