How to get the current running module path/name
Asked Answered
P

8

46

I've searched and this seems to be a simple question without a simple answer.

I have the file a/b/c.py which would be called with python -m a.b.c. I would like to obtain the value a.b.c in the module level.

USAGE = u'''\
Usage:
    python -m %s -h
''' % (what_do_i_put_here,)

So when I receive the -h option, I display the USAGE without the need to actually write down the actual value in each and every script.

Do I really need to go through inspect to get the desired value?

Thanks.

EDIT: As said, there are answers (I've searched), but not simple answers. Either use inspect, use of traceback, or manipulate __file__ and __package__ and do some substring to get the answer. But nothing as simple as if I had a class in the module, I could just use myClass.__module__ and I would get the answer I want. The use of __name__ is (unfortunately) useless as it's always "__main__".

Also, this is in python 2.6 and I cannot use any other versions.

Pickings answered 3/3, 2011 at 16:32 Comment(3)
Does this thread help you? #248270Diligent
There are multiple candidates for duplicates: #4289405, #1450978Revisionist
I think this is not a duplicate: The, in the previous comments, referenced issues aim to get the path of the executing file on the file system whereas the PO wants to get the current python package + moduleMigration
E
33

This works for me:

__loader__.fullname

Also if I do python -m b.c from a\ I get 'b.c' as expected.

Not entirely sure what the __loader__ attribute is so let me know if this is no good.

edit: It comes from PEP 302: http://www.python.org/dev/peps/pep-0302/

Interesting snippets from the link:

The load_module() method has a few responsibilities that it must fulfill before it runs any code:

...

  • It should add an __loader__ attribute to the module, set to the loader object. This is mostly for introspection, but can be used for importer-specific extras, for example getting data associated with an importer.

So it looks like it should work fine in all cases.

Excel answered 9/1, 2012 at 14:10 Comment(1)
For me it needs to be __loader__.name. See doc at docs.python.org/3/library/…Karlynkarma
C
20

I think you're actually looking for the __name__ special variable. From the Python documentation:

Within a module, the module’s name (as a string) is available as the value of the global variable __name__.

If you run a file directly, this name will __main__. However, if you're in a module (as in the case where you're using the -m flag, or any other import), it will be the complete name of the module.

Challis answered 3/3, 2011 at 17:6 Comment(3)
__name__ will be "main" if it is called with the "-m" flag.Pickings
if you want more pythonic way to get the module name without the -m option in cmd or terminal, or dont want to use loader you might be interested to check my answer somewhere below. its a one liner , uses string manipulation. regards.Thracophrygian
In my case I needed the main module of a chain of submodules, for example tf.keras.layers. So I used __name__.split('.')[0]Cursory
P
10

When run with -m, sys.path[0] contains the full path to the module. You could use that to build the name.

source: http://docs.python.org/using/cmdline.html#command-line

Another option may be the __package__ built in variable which is available within modules.

Polyneuritis answered 3/3, 2011 at 16:46 Comment(2)
Thanks I edited my question to specify that I know how to manipulate to get the answer, I was hoping for an easier way without having to validate it myself.Pickings
You meant sys.argv[0].Estes
S
10

Number of options are there to get the path/name of the current module.

First be familiar with the use of __file__ in Python, Click here to see the usage.

It holds the name of currently loaded module.

Check/Try the following code, it will work on both Python2 & Python3.

» module_names.py

import os

print (__file__)
print (os.path.abspath(__file__))
print (os.path.realpath(__file__))

Output on MAC OS X:

MacBook-Pro-2:practice admin$ python module_names.py 
module_names.py
/Users/admin/projects/Python/python-the-snake/practice/module_names.py
/Users/admin/projects/Python/python-the-snake/practice/module_names.py

So here we got the name of current module name and its absolute path.

Salvadorsalvadore answered 1/12, 2017 at 1:36 Comment(0)
I
0

The only way is to do path manipulation with os.getcwd(), os.path, file and whatnot, as you mentioned.

Actually, it could be a good patch to implement for optparse / argparse (which currently replace "%prog" in the usage string with os.path.basename(sys.argv[0]) -- you are using optparse, right? -- ), i.e. another special string like %module.

Isabea answered 6/1, 2012 at 11:13 Comment(1)
I'm still actually using a company package that still use getopt. Module was created back in 2006-2007?Pickings
T
-2

One liner But OS dependent

it does not work in interpreter! since file is meaningless there in the interpreter and is not defined.

does not require os module to be imported.

modulename=__file__.split("\\")[-1].split('.')[0]

Explanation: X:\apple\pythonabc.py | will output pythonabc.py

select the last element after splitting with slashes, then select the first element by splitting it with dot '.'. because first step gives module.py, second step gives 'module' only. __file__ is a unique variable and returns the filepath of current module.

Comment any flaws or has any other pitfalls.

Thracophrygian answered 17/9, 2020 at 0:48 Comment(3)
Did you even try this with the example path/file and python command given at the very start of the question?Cruces
python -m test gives test, but no success for test.b.c . partially answers the OPs question. somebody might get other idea if they stumble here via google. there are many ways to solve problem. and sometimes simple is not solution.Thracophrygian
It does not even partially answer, because the OP wants the module name, and Python filenames are not module names.Cruces
P
-3

you should hardcode a.b.c in your help, if you distribute the package as such then that's the way to call it regardless of where a is located in the filesystem, as long as it's on the PYTHONPATH it'll be imported.

Powwow answered 9/1, 2012 at 16:2 Comment(10)
This defies the purpose of my need. The problem of hardcoding is always if I change the name of my file, I need to remember to change the help text.Pickings
if you change the name of the file all the imports will break so the help text is the lesser of your problems.Powwow
The script being the entry point, it is not imported by other modules so this problem doesn't apply.Pickings
that contradicts your original question, in fact if that's the case __name__ == "__main__" works as usual.Powwow
Sorry to disagree. I don't see how changing the name of my current file will break imports in it. I've been developing for 5 years and changing the name of an entry point (scripts) never broke any of the imports in it. If you have a concrete example, please enlighten me. If you are referring to "relative" imports, I NEVER use them.Pickings
it's ok to disagree if you have a reason, the thing here is that the entry point isn't (normally) imported but it's instead executed so in that case it doesn't matter but here you were talking about imports so then it's a different thing and what doesn't make sense is that you import the entry point, that's the contradiction.Powwow
Actually, you were the one who first mentionned imports: "if you change the name of the file all the imports will break".Pickings
yes, because changing the name of the file you execute shouldn't matter, you don't need to know 'a.b.c' if it's the entry point because you don't du 'python -m a.b.c' you do 'python filename'Powwow
but that's my whole point, WHY do "python -m a.b.c" instead of "python file" huh? i don't give a shit about SO if you ask nonsense I'll call you up on it, I don't care if I don't answer your question, the real answer is "you're doing it wrong"Powwow
That's your opinion. I am using "python -m a.b.c" because I want to install the script along with my python modules. I don't want to pollute /usr/local/bin or any of the virtualenv/bin. Doing so, I am protecting myself by using the wrong module with the wrong python environment.Pickings
P
-3

Why does nobody mentioned the .__module__?

When doing a self.__module__ you will get the module path. You can also do this outside of the class:

Class A:
   self.__module__  # gets module.filename

def get_module():
    A.__module__ # also gets module.filename
Plater answered 17/4, 2018 at 14:17 Comment(1)
Thanks for your comment and downvote. I didn't read your edit so I guess it's fair..Plater

© 2022 - 2024 — McMap. All rights reserved.