Finding a module's directory - python

How can I find what directory a module has been imported from, as it needs to load a data file which is in the same directory.
edit:
combining several answers:
module_path = os.path.dirname(imp.find_module(self.__module__)[1])
got me what i wanted

If you want to modules directory by specifying module_name as string i.e. without actually importing the module then use
def get_dir(module_name):
import os,imp
(file, pathname, description) = imp.find_module(module_name)
return os.path.dirname(pathname)
print get_dir('os')
output:
C:\Python26\lib
foo.py
def foo():
print 'foo'
bar.py
import foo
import os
print os.path.dirname(foo.__file__)
foo.foo()
output:
C:\Documents and Settings\xxx\My Documents
foo

This would work:
yourmodule.__file__
and if you want to find the module an object was imported from:
myobject.__module__

The path to the module's file is in module.__file__. You can use that with os.path.dirname to get the directory.

Using the re module as an example:
>>> import re
>>> path = re.__file__
>>> print path
C:\python26\lib\re.pyc
>>> import os.path
>>> print os.path.dirname(os.path.abspath(path))
C:\python26\lib
Note that if the module is in your current working directory ("CWD"), you will get just a relative path e.g. foo.py. I make it a habit of getting the absolute path immediately just in case the CWD gets changed before the module path gets used.

Related

I try to get to the directory of where the current python script is located [duplicate]

How do I get the current file's directory path?
I tried:
>>> os.path.abspath(__file__)
'C:\\python27\\test.py'
But I want:
'C:\\python27\\'
The special variable __file__ contains the path to the current file. From that we can get the directory using either pathlib or the os.path module.
Python 3
For the directory of the script being run:
import pathlib
pathlib.Path(__file__).parent.resolve()
For the current working directory:
import pathlib
pathlib.Path().resolve()
Python 2 and 3
For the directory of the script being run:
import os
os.path.dirname(os.path.abspath(__file__))
If you mean the current working directory:
import os
os.path.abspath(os.getcwd())
Note that before and after file is two underscores, not just one.
Also note that if you are running interactively or have loaded code from something other than a file (eg: a database or online resource), __file__ may not be set since there is no notion of "current file". The above answer assumes the most common scenario of running a python script that is in a file.
References
pathlib in the python documentation.
os.path - Python 2.7, os.path - Python 3
os.getcwd - Python 2.7, os.getcwd - Python 3
what does the __file__ variable mean/do?
Using Path from pathlib is the recommended way since Python 3:
from pathlib import Path
print("File Path:", Path(__file__).absolute())
print("Directory Path:", Path().absolute()) # Directory of current working directory, not __file__
Note: If using Jupyter Notebook, __file__ doesn't return expected value, so Path().absolute() has to be used.
In Python 3.x I do:
from pathlib import Path
path = Path(__file__).parent.absolute()
Explanation:
Path(__file__) is the path to the current file.
.parent gives you the directory the file is in.
.absolute() gives you the full absolute path to it.
Using pathlib is the modern way to work with paths. If you need it as a string later for some reason, just do str(path).
Try this:
import os
dir_path = os.path.dirname(os.path.realpath(__file__))
import os
print(os.path.dirname(__file__))
I found the following commands return the full path of the parent directory of a Python 3 script.
Python 3 Script:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pathlib import Path
#Get the absolute path of a Python3.6 and above script.
dir1 = Path().resolve() #Make the path absolute, resolving any symlinks.
dir2 = Path().absolute() #See #RonKalian answer
dir3 = Path(__file__).parent.absolute() #See #Arminius answer
dir4 = Path(__file__).parent
print(f'dir1={dir1}\ndir2={dir2}\ndir3={dir3}\ndir4={dir4}')
REMARKS !!!!
dir1 and dir2 works only when running a script located in the current working directory, but will break in any other case.
Given that Path(__file__).is_absolute() is True, the use of the .absolute() method in dir3 appears redundant.
The shortest command that works is dir4.
Explanation links: .resolve(), .absolute(), Path(file).parent().absolute()
USEFUL PATH PROPERTIES IN PYTHON:
from pathlib import Path
#Returns the path of the current directory
mypath = Path().absolute()
print('Absolute path : {}'.format(mypath))
#if you want to go to any other file inside the subdirectories of the directory path got from above method
filePath = mypath/'data'/'fuel_econ.csv'
print('File path : {}'.format(filePath))
#To check if file present in that directory or Not
isfileExist = filePath.exists()
print('isfileExist : {}'.format(isfileExist))
#To check if the path is a directory or a File
isadirectory = filePath.is_dir()
print('isadirectory : {}'.format(isadirectory))
#To get the extension of the file
fileExtension = mypath/'data'/'fuel_econ.csv'
print('File extension : {}'.format(filePath.suffix))
OUTPUT:
ABSOLUTE PATH IS THE PATH WHERE YOUR PYTHON FILE IS PLACED
Absolute path : D:\Study\Machine Learning\Jupitor Notebook\JupytorNotebookTest2\Udacity_Scripts\Matplotlib and seaborn Part2
File path : D:\Study\Machine Learning\Jupitor Notebook\JupytorNotebookTest2\Udacity_Scripts\Matplotlib and seaborn Part2\data\fuel_econ.csv
isfileExist : True
isadirectory : False
File extension : .csv
works also if __file__ is not available (jupyter notebooks)
import sys
from pathlib import Path
path_file = Path(sys.path[0])
print(path_file)
Also uses pathlib, which is the object oriented way of handling paths in python 3.
IPython has a magic command %pwd to get the present working directory. It can be used in following way:
from IPython.terminal.embed import InteractiveShellEmbed
ip_shell = InteractiveShellEmbed()
present_working_directory = ip_shell.magic("%pwd")
On IPython Jupyter Notebook %pwd can be used directly as following:
present_working_directory = %pwd
I have made a function to use when running python under IIS in CGI in order to get the current folder:
import os
def getLocalFolder():
path=str(os.path.dirname(os.path.abspath(__file__))).split(os.sep)
return path[len(path)-1]
Python 2 and 3
You can simply also do:
from os import sep
print(__file__.rsplit(sep, 1)[0] + sep)
Which outputs something like:
C:\my_folder\sub_folder\
This can be done without a module.
def get_path():
return (__file__.replace(f"<your script name>.py", ""))
print(get_path())

Proper way to dynamically import a module with relative imports?

I need to dynamically import modules into my project from another package.
The structure is like:
project_folder/
project/
__init__.py
__main__.py
plugins/
__init__.py
plugin1/
__init__.py
...
plugin2/
__init__.py
...
I made this function to load a module:
import os
from importlib.util import spec_from_file_location, module_from_spec
def load_module(path, name=""):
""" loads a module by path """
try:
name = name if name != "" else path.split(os.sep)[-1] # take the module name by default
spec = spec_from_file_location(name, os.path.join(path, "__init__.py"))
plugin_module = module_from_spec(spec)
spec.loader.exec_module(plugin_module)
return plugin_module
except Exception as e:
print("failed to load module", path, "-->", e)
It works, unless the module uses relative imports:
failed to load module /path/to/plugins/plugin1 --> Parent module 'plugin1' not loaded, cannot perform relative import
What am I doing wrong?
I managed to solve my own issue after a LOT of googling. Turns out I needed to import using relative paths:
>>> from importlib import import_module
>>> config = import_module("plugins.config")
>>> config
<module 'plugins.config' from '/path/to/plugins/config/__init__.py'>
>>>
I had a similar problem not long ago. I added the path of the project folder to the sys.path using the module's absolute path like this:
import sys
import os
sys.path.append(os.path.dirname(os.path.realpath(__file__))+'/..')
This adds the project_folder to the sys.path thus allowing the import statement to find the plugin modules.

How to change built_in module in python

I want to change os.path in os.py, but it failed. path is different in different platform.
os.py
import ntpath as path
sys.modules['os.path'] = path
from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep, devnull)
It turns out that
from os.path import (curdir, pardir, sep, pathsep, defpath, extsep, altsep,
devnull)
ImportError: No module named path
Your approach should work. Rename the subdirectory os in your current directory to my_os. Python finds your os directory first and tries to import from there.
Adding this line:
__future__ import absolute_import
to the beginning of the os.py avoids this problem by using absolute imports.
did you try with "__import__" function ?
import mtpath as path
os_path = __import__(path, globals(), locals(), ['curdir', 'pardir', 'sep', 'pathsep', 'defpath', 'extsep', 'altsep', 'devnull']
Then, you can use 'curdir' as :
os_path.curdir
Well, you can also asign it to 'curdir' name as in the documentation :
curdir = os_path.curdir
pardir = os_path.curdir
…

import module from another path cause IOERROR:NO such file or directory

this is a visual representation of my directory :
here is the code snippet from test1.py
....
def foo():
f=read("./test1.dat","r")
....
here is the code of test2.py
import imp
TEST1 = imp.load_source('test1', '../test1.py')
def test2():
TEST1.foo()
running test2.py
cd subdir
python test2.py
got IOERROR: No Such file or directory : "./test1.dat"
my question is :
if I don't change the structure of directory, for example move test2.py to its parent directory, is it possible to make module test1 find the correct file when calling it in module test2?
This will give you the path to a module that was loaded:
import a_module
print a_module.__file__
To get the directory of the module:
import os, a_module
path = os.path.dirname(a_module.__file__)
Putting it all together, I'd use this approach if you're looking for files relative to another module:
from test1.py
def foo(path):
f=read(path,"r")
from test2.py
import os, test1
path = os.path.dirname(test1.__file__)
test1.foo(path + "/test1.dat")

Reload all modules in a directory

I need to reload all the python modules within a specified directory.
I've tried something like this:
import sys, os
import_folder = "C:\\myFolder"
sys.path.insert( 0 , import_folder )
for dir in os.listdir(import_folder):
name = os.path.splitext(dir)[0]
ext = os.path.splitext(dir)[1]
if ext == ".py":
import( eval(name) )
reload( eval(name) )
Anyone know how to do this correctly?
import os # we use os.path.join, os.path.basename
import sys # we use sys.path
import glob # we use glob.glob
import importlib # we use importlib.import_module
import_folder = 'C:\\myFolder'
sys.path.append(import_folder) # this tells python to look in `import_folder` for imports
for src_file in glob.glob(os.path.join(import_folder, '*.py')):
name = os.path.basename(src_file)[:-3]
importlib.import_module(name)
reload(sys.modules[name])
importlib.import_module(name)
There is the code. Now to the semantics of the whole thing: using importlib makes this a little bit more normal, but it still promotes some bugs. You can see that this breaks for source files in a subdirectory. What you should probably do is: import the package, (import the whole folder), and use the . operator like so:
import sys # we use sys.path
sys.path.append('C:\\')
import myFolder
...
myFolder.func1(foo)
myFolder.val
bar = myFolder.Class1()
Perhaps you should take a look at the documentation for modules, but don't forget to update the path to include the parent of the folder you want to import.

Categories