If I see a code or I am repairing defunct code I would need to know, where the specific object is located. I. e. in which library and under which class, etc. What are the ways to figure it out?
Can you show an example please?
Iād rather not guess at what problem you are asking for help with.
Modern source code editors, e.g. VS Code, let you right click and go to the definition etc. of a symbol.
So in the past you were lost and you have to browse internet or ask someone?
I read the sources of the package that I have installed.
If you are not sure where the sources are you can just import the package and print the repr of the package. This includes the path of the .py file.
import pathlib
print(repr(pathlib))
For example. I want to get build-in help on count()
(method). If I type help(count)
I receive an error. How can I know that itās a method of the string and I should be calling the help via help(str.count)
?
Thats good when you know the library. What about if you dont know the library?
How can I know that itās a method of the string and I should be calling the help via
help(str.count)
?
You stop coding in notepad.exe, and install a modern source code editor with āintellisenseā instead.
What about if you dont know the library?
Pythonās namespace and import syntax mean that if a name is defined in a module or script, it was defined in the same module (in a parent scope of whereever it is referred to), or itās a built in, or it was imported. In the latter case import statements require the library or sub module the name came from to be specified (*).
How else could the interpreter know where to fetch the code for a particular imported function from?
āNamespaces are one honking great idea ā letās do more of those!ā
(*) At least by its import name. Tracking down the actual name of the library, e.g. on PyPi can be harder. For that you need to look in pyproject.toml, requirements.txt or setup.py and work it out.
Using modern IDEs is definitely a good thing. But the question of āhow does python resolve imported codeā really shouldnāt be dismissed. Itās a fair question that I think a lot of people would wonder, at LEAST for instructive purposes if not to help them build some tool. It would be nice to see a flow chart outlining how python resolves code when you make an import statement.
I know that when you make an import statement then python crawls the python path environment variable searching for a package with the same name as the import statement, but Iām not exactly sure how this works because the top level directory name may not match the import name. Iāve never understood how this difference gets resolvedā¦
Seems like itās described in details here: 5. The import system ā Python 3.12.0 documentation, but there is indeed no flowchart.
Iāve never thoroughly read through that documentation but I think youāre right that the answers to my questions (and probably the OPs?) are found there. I think the minor comment about the site package is also important in there.
So I think the answer to the OPs question would be something like: look at the top level import name for the package being imported, then, if itās not a built in, then look at your python path and follow the linked to documentation to figure out where in the path your import got resolved. In most cases on my windows machine there is a directory with the same name as the import name in the site-packages
folder for my python (virtual) environment and there are .py
files in that directory (or in nested directories/sub-packages in that directory) which is where the code is being imported from.
Look at the __class__
attribute of something (or the type). If itās not a module, then first find out from which module it came (or whether itās a builtin). If itās a module, then look at module.__file__
.
>>> import uuid
>>> uuid.__class__
<class 'module'>
>>> uuid.__file__
'/Users/{my_login_name}/miniconda3/lib/python3.10/uuid.py'
>>> import pandas as pd
>>> pd.__file__
'/Users/{my_login_name}/miniconda3/lib/python3.10/site-packages/pandas/__init__.py'
This works for the count case:
>>> help(''.count)
Help on built-in function count:
count(...) method of builtins.str instance
S.count(sub[, start[, end]]) -> int
Return the number of non-overlapping occurrences of substring sub in
string S[start:end]. Optional arguments start and end are
interpreted as in slice notation.
Also you can find out the type of an object, a string in this case, like this:
>>> type('')
<class 'str'>
@Juandev 's question is ā what if he doesnāt know where count
is coming from. But that question doesnāt really make sense in Python: you always know this!
In this example, you will never just see a naked ācountā function, but you will only see s.count()
where (you can easily see or guess that) s
is the name of some string. In the cases where you do come across a naked function (or class or whatever) name, it will always be inside some module, so itās either some undefined name or itās defined in that module itself or imported (with
from mystery_module.submodule import mystery_function
or some similar statement).
Names are always part of some namespaceā¦
(Of course all this becomes a lot harder to trace when people start doing
from module import *
which should really be outlawed.)
It can be also one of built-in functions.
The other example and again from the area of help is pass
. If I type in help(pass)
I receive an error. So I should browse the Internet on what is pass
and finally get the answer, that it is a keyword and in that case, you type in help("pass")
.
Before I learned bash. Looking for help was straightforward. You had a few ways how to get some manual pages (man *str*
, info *str*
, etc.) and that was it. Sometimes there were not man pages at all. With Python, you have to know what type of object you are dealing with and where it is located, to get the help.
I would have expected that you would have learnt about the few keywords used by python in a python tutorial. help() is not supposed to deal with keywords.
Actually Python does help with keywords (Python 3.11.5) (and I actually only found this out while reading this thread!):
>>> help("pass")
The "pass" statement
********************
pass_stmt ::= "pass"
"pass" is a null operation ā when it is executed, nothing happens. It
is useful as a placeholder when a statement is required syntactically,
but no code needs to be executed, for example:
def f(arg): pass # a function that does nothing (yet)
class C: pass # a class with no methods (yet)
The thing is you do need to quote term, since you cannot call any function that takes a bare-bones keyword as argument. I wanted to write āyou need to quote the term of courseā but this may not be very obvious to people who just started learning Python as first programming languageā¦
So actually help(help)
could perhaps be improved a (tiny) bit:
Instead of
>>> help(help)
....
| Calling help() at the Python prompt starts an interactive help session.
| Calling help(thing) prints help for the python object 'thing'.
the following might be better:
....
| Calling help() at the Python prompt starts an interactive help session.
| Calling help(thing) prints help for the python object 'thing'. If 'thing'
| is a Python keyword like 'if', 'else', 'for', calling help("thing") with
| the quoted keyword prints help.
Well, yes; the complaint was that the quotes are necessary. OP tried help(pass)
, which canāt work, because help
is an ordinary Python function, and the REPL accepts Python code, not ācommandsā.
Imagine you saw someone elseās bash example like ls > /dev/null
, and you didnāt understand what the >
meant. So you tried man >
, and info >
, and got Bash syntax errors. Itās the same problem - except that in this case quoting doesnāt even help; as you say,
But then, the reason there are any man pages is because Linux derives from Unix, and Unix has existed for far longer than the Internet has been a useful research tool. Which brings me toā¦
Python, on the other hand, is barely any older than the World Wide Web, and really hit its stride (in my assessment) around the same time that Youtube appeared. So itās hardly surprising that people are expected to look online for help. You donāt have to do searches, though. The documentation is all in one place, which is named very much like one would expect: https://docs.python.org .
Yes, itās a little obnoxious that you seemingly have to understand that much about pass
in order to be able to use it with the help
command. But actually, you can just have the rule of always passing a string: help("str.count")
works, and gives the same information as help(str.count)
. You can also access the help from the command line: python -m pydoc pass
, or python -m pydoc str.count
. And anyway, documentation canāt really teach you how to use tools. Reading the man pages wonāt teach you how to write shell scripts, either.