5

Situation: We know that the below will check if the script has been called directly.

if __name__ == '__main__':
    print "Called directly"

else:
    print "Imported by other python files"

Problem: The else clause is only a generic one and will run as long as the script was not called directly.

Question: Is there any way to get which file it was imported in, if it is not called directly?

Additional information: Below is an example of how I envisioned the code would be like, just that I do no know what to put in <something>.

if __name__ == '__main__':
    print "Called directly"

elif <something> == "fileA.py":
    print "Called from fileA.py"

elif <something> == "fileB.py":
    print "Called from fileB.py"

else:
    print "Called from other files"
Timothy Wong
  • 689
  • 3
  • 9
  • 28
  • For what do you need the calling file name? – mrCarnivore Jan 25 '18 at 08:48
  • 1
    I'm not sure that you really want to do this. There is a principle of dependencies where something that is depended upon should not know or care what depends upon it. In Python, like lots of languages there can be lots of other modules which import this module. Therefore your `` will actually contain different things in quick sucession. – quamrana Jan 25 '18 at 08:50
  • @mrCarnivore I may need the code to run different things depends on the file that called it. – Timothy Wong Jan 25 '18 at 08:53
  • 3
    @TimothyWong You do not want to do this. Typically a function or a module does not change its behavior depending on what calls it. Try passing arguments around instead that are handled by the function or module. – Ma0 Jan 25 '18 at 08:55
  • @Ev.Kounis yep. I realised it 30 seconds after I posted the question that I could just pass a variable, but wonder if there is a more direct way to do it – Timothy Wong Jan 25 '18 at 08:56
  • Maybe you could set a global in the code containing the `import` statement. Then the imported module can test the value of that global. But I agree with others that this is **not** a good design as it breaks modularity, and hence will make your program much harder to develop, read, and debug. – PM 2Ring Jan 25 '18 at 08:58
  • @PM2Ring I do understand the dangers of global variables, which is actually why I am posting the question cause I cannot think of a better way to do it – Timothy Wong Jan 25 '18 at 09:00
  • 1
    The usual warning against using globals is because they break modularity within a module. Without globals you just need to understand each function separately, but with globals you need to see how all the functions affect each other through the global variable "leakage". But what you're proposing is even worse: it breaks modularity of the whole program, so you can't simply understand each module separately, you need to see how they all affect each other. So you might as well not even bother creating separate modules, just write it as one big unreadable mess of spaghetti code. ;) – PM 2Ring Jan 25 '18 at 09:16
  • @PM2Ring I see. I'll see what I can do about it in the meantime. Thanks. – Timothy Wong Jan 25 '18 at 09:17

2 Answers2

2

Try this:-

import sys
print sys.modules['__main__'].__file__

Refer for better answer:- How to get filename of the __main__ module in Python?

AlokThakur
  • 3,599
  • 1
  • 19
  • 32
  • This works, but do you happen to know a way that does not need the module `sys` to be imported? The SBC I am working with apparently has a problematic `sys` module and I am staying clear of it... – Timothy Wong Jan 25 '18 at 09:03
  • 1
    no, I don't know a solution which works without "sys" module, I will keep this answer to help who can work with "sys" module. – AlokThakur Jan 25 '18 at 09:09
  • 1
    Awww... sure thing! Thanks a lot -- I will accept it as an answer if no one can do it w/o the `sys` module. – Timothy Wong Jan 25 '18 at 09:14
  • 1
    Found my answer. Do you mind putting this link into your answer + precautions mentioned in the comments? I'll accept it as an answer after the change. https://stackoverflow.com/questions/606561/how-to-get-filename-of-the-main-module-in-python – Timothy Wong Jan 25 '18 at 09:19
1

There are a couple different methods you may like to be aware of depending on what you're trying to accomplish.

The inspect module has a getfile() function which can be used to determine the name of the currently-executing function.

Example:

#!/usr/bin/env python3
import inspect
print(inspect.getfile(inspect.currentframe()))

Result:

test.py

To find out which command-line arguments were used to execute a script, you'll need to use sys.argv

Example:

#!/usr/bin/env python3
import sys
print(sys.argv)

Result when invoked with ./test.py a b c:

['./test.py', 'a', 'b', 'c']

Result when invoked with python3 test.py a b c:

['test.py', 'a', 'b', 'c']

Hope this helps!

Max
  • 913
  • 1
  • 7
  • 18