1

Let's say I have imported two modules like this:

from module0 import hello_func
from directory.module1 import hello_var

Where in module0:

def hello_func(): return "hello from module0"

And module1:

hello_var = "hello from module1"

How can I know from which file is each object being imported?

I tried to check locals() function but nothing in there giving reference to the file...

  • 1
    Stop using `from ... import *`. If you write `from module0 import hello_func` and `from directory.module1 import hello_var`, this is a non-issue. Both modules should *document* what values exist in the module and can be imported like this. – chepner Dec 17 '19 at 16:28
  • @chepner Other than variable overriding is there any other issue using it? – Mohamed Msd Dec 17 '19 at 16:30
  • 1
    I'd argue the lack of transparency about what just got added to the global namespace is the primary problem. The overriding is just a symptom, because you might define a name `foo` which wasn't obviously imported from `module0`. – chepner Dec 17 '19 at 16:33

4 Answers4

0

You can define in each module a constant with its path, something like this should work:

import os

FILE_PATH = os.path.abspath(__file__)

When you import that module you can access its location like this:

import module

print(module.FILE_PATH)
marcos
  • 4,473
  • 1
  • 10
  • 24
  • When is `__file__` *not* already an absolute path? (I think it is, but I could be mistaken.) – chepner Dec 17 '19 at 16:36
  • it could be a relative path, and then you will get wrong paths, always try to use absolute paths. – marcos Dec 17 '19 at 16:38
  • That's my question: *when* is it a relative path? I'm under the impression that it will always be set to the absolute path of the module to begin with, assuming the module comes from a file at all. – chepner Dec 17 '19 at 16:39
  • consider reading this: https://stackoverflow.com/questions/7116889/is-module-file-attribute-absolute-or-relative – marcos Dec 17 '19 at 16:40
  • Because it doesn't actually answer the question, perhaps ? (just guessing...) – bruno desthuilliers Dec 17 '19 at 16:49
  • 2
    The question asks about identifying which module a name was imported from, not which file a module was read from. – chepner Dec 17 '19 at 17:00
  • 1
    Actually what he asked was this: How can I know from which file is each object being imported? What uniquely identifies a file is its absolute path. – marcos Dec 17 '19 at 17:01
  • I'm with @Marcos on this one! – DUDANF Dec 17 '19 at 17:07
0

Another solution using the inspect and os modules.

import module0
import os
import inspect

print(os.path.abspath(inspect.getfile(module0.hello_func)))
Nuno Palma
  • 514
  • 3
  • 9
  • Raising Exception: " is not a module, class, method, function, traceback, frame, or code object" – Mohamed Msd Dec 17 '19 at 16:40
  • To be pedantic: in Python everything is an object, so "this doesn't work on variables" is actually false - a function, class etc IS a "variable". The distinction is whether the inspected object does keep trace of where it was defined. This is the case for functions, classes, tracebacks, etc, but not for most other types. – bruno desthuilliers Dec 17 '19 at 16:47
0

Actually, you kind of answered your question yourself:

Let's say I have imported two modules
(insert "from xxx import *" here)
How can I know from which file is each object being imported?

One of the reasons of NOT using wildcard imports is precisely to make it clear where names are imported from (the other one being to avoind one imported name to shadow a previously imported one - something that tends to break you code in the most unexpected - and sometimes quite hard to spot - ways).

Note that in your edited question:

from module0 import hello_func
from directory.module1 import hello_var

you already have a much better idea where a name comes from. Not the exact files path yet, but at least the name of the package/module.

And that's one of the main reasons why one should NOT use wildcard imports.

Now if you want to know the exact files path, you have two distinct cases.

Some objects keep trace of where they were created (mostly modules, classes, functions, etc - cf the list of types supported by inspect.getfile()), and then, well, you already know the answer (use inspect.getfile() xD).

But most types wont (because there's no reason for it). In this case, you have to know which module they were imported from and call inspect.getfile() on the module itself. In this case, if you used wildcard imports, you will have to manually inspect all the modules you imported from to find out which one defined this name. Enjoy. Specially if one of those modules did also use wildcard imports...

one question please: where they does keep traces? and how these traces look like?

Modules keep it in their __file__ attribute. Functions and classes keep a reference to their module's name in their __module__ attribute, and from this you can use it to retrieve the module from the sys.modules dict (a cache of all modules already imported in the current process), which will gives you the file.

I never had a need to search this info for tracebacks, frames, code objects etc so you'll have to check it yourself I'm afraid ;-)

bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
0

If you are looking for the absolute path of where the script is being run, this should work for sure:

import os
abs_path = os.path.dirname(os.path.abspath(__file__))
print(abs_path)
DUDANF
  • 2,618
  • 1
  • 12
  • 42