Python | os.path.realpath () method

Python Methods and Functions | realpath

The Python OS module provides functions for interacting with the operating system. The OS comes with standard Python service modules. This module provides a portable way to use operating system specific functionality. The os.path module is a submodule of the Python OS module that is used to manage shared paths. os.path.realpath () in Python is used to get the canonical path of the specified filename by removing any symbolic links that occur in the path.
Syntax: os.path.realpath(path)

path: A path-like object representing the file system path.
A path-like object is either a string or bytes object representing a path.

Return Type: This method returns a string value which represents the canonical path.

Create soft link or symbolic link

On Unix or Linux, a soft link or symbolic link can be created using the ln command. Following is the syntax for creating a symbolic link on the command line:
$ ln -s {source-filename} {symbolic-filename}

Example 1

def realpath(self, spec, key):
        Resolve and update the path key in the spec with its realpath,
        based on the working directory.

        if key not in spec:
            # do nothing for now

        if not spec[key]:
                "cannot resolve realpath of '%s' as it is not defined", key)

        check = realpath(join(spec.get(WORKING_DIR, ''), spec[key]))
        if check != spec[key]:
            spec[key] = check
                "realpath of '%s' resolved to '%s', spec is updated",
                key, check
        return check

    # Setup related methods 

Example 2

def get_rp_stripper(strip_path):
    """ Return function to strip ''realpath'' of 'strip_path' from string

    strip_path : str
        path to strip from beginning of strings. Processed to ''strip_prefix''
        by ''realpath(strip_path) + os.path.sep''.

    stripper : func
        function such that ''stripper(a_string)'' will strip ''strip_prefix''
        from ''a_string'' if present, otherwise pass ''a_string'' unmodified
    return get_prefix_stripper(realpath(strip_path) + os.path.sep) 

Example 3

def test_toolchain_standard_not_implemented(self):
        spec = Spec()

        with self.assertRaises(NotImplementedError):

        with self.assertRaises(NotImplementedError):

        with self.assertRaises(NotImplementedError):

        # Check that the build_dir is set on the spec based on tempfile
        # Also that it got deleted properly.

Example 4

def find_system_jdks():
    Returns a set of valid JDK directories by searching standard locations.
    bases = [
        r'C:\Program Files\Java'
    jdks = set()
    for base in bases:
        if isdir(base):
            for n in os.listdir(base):
                jdk = join(base, n)
                mac_jdk = join(jdk, 'Contents', 'Home')
                if isdir(mac_jdk):
                    jdk = mac_jdk
                if is_valid_jdk(jdk):
    return jdks 

Example 5

def _expand_dirs_to_files(files_or_dirs, recursive=False):
    files = []
    files_or_dirs = _ensure_list(files_or_dirs)
    for file_or_dir in files_or_dirs:
        file_or_dir = op.realpath(file_or_dir)
        if op.isdir(file_or_dir):
            # Skip dirnames starting with '.'
            if _to_skip(file_or_dir):
            # Recursively visit the directories and add the files.
            if recursive:
                files.extend(_expand_dirs_to_files([op.join(file_or_dir, file)
                             for file in os.listdir(file_or_dir)],
                files.extend([op.join(file_or_dir, file)
                              for file in os.listdir(file_or_dir)])
        elif '*' in file_or_dir:
    return files 

Example 6

def getSubdirs(path, baseNamesOnly=True, excludePythonModulesDirs=True):
    """Provides a list of sub directories for the given path"""
    subdirs = []
        path = realpath(path) + sep
        for item in os.listdir(path):
            candidate = path + item
            if isdir(candidate):
                if excludePythonModulesDirs:
                    modFile = candidate + sep + ""
                    if exists(modFile):
                if baseNamesOnly:
    return subdirs 

Example 7

def get_dataset(num_points):
    name = 'ModelNet10'
    path = osp.join(osp.dirname(osp.realpath(__file__)), '..', 'data', name)
    pre_transform = T.NormalizeScale()
    transform = T.SamplePoints(num_points)

    train_dataset = ModelNet(
    test_dataset = ModelNet(

    return train_dataset, test_dataset 

Example 8

def getParameters(self):
        """Provides a dictionary with the search parameters"""
        parameters = {'term': self.findCombo.currentText(),
                      'case': self.caseCheckBox.isChecked(),
                      'whole': self.wordCheckBox.isChecked(),
                      'regexp': self.regexpCheckBox.isChecked()}
        if self.projectRButton.isChecked():
            parameters['in-project'] = True
            parameters['in-opened'] = False
            parameters['in-dir'] = ''
        elif self.openFilesRButton.isChecked():
            parameters['in-project'] = False
            parameters['in-opened'] = True
            parameters['in-dir'] = ''
            parameters['in-project'] = False
            parameters['in-opened'] = False
            parameters['in-dir'] = realpath(
        parameters['file-filter'] = self.filterCombo.currentText().strip()

        return parameters 

Example 9

def _check_if_pyc(fname):
    """Return True if the extension is .pyc, False if .py
    and None if otherwise"""
    from imp import find_module
    from os.path import realpath, dirname, basename, splitext

    # Normalize the file-path for the find_module()
    filepath = realpath(fname)
    dirpath = dirname(filepath)
    module_name = splitext(basename(filepath))[0]

    # Validate and fetch
        fileobj, fullpath, (_, _, pytype) = find_module(module_name, [dirpath])
    except ImportError:
        raise IOError("Cannot find config file. "
                      "Path maybe incorrect! : {0}".format(filepath))
    return pytype, fileobj, fullpath 

Example 10

def get_planetoid_dataset(name, normalize_features=False, transform=None):
    path = osp.join(osp.dirname(osp.realpath(__file__)), '..', 'data', name)
    dataset = Planetoid(path, name)

    if transform is not None and normalize_features:
        dataset.transform = T.Compose([T.NormalizeFeatures(), transform])
    elif normalize_features:
        dataset.transform = T.NormalizeFeatures()
    elif transform is not None:
        dataset.transform = transform

    return dataset 

Example 11

def _setup_logger(cls, log_file=None):
        formatter = logging.Formatter(
            fmt="%(asctime)s %(levelname)-8s %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
        screen_handler = logging.StreamHandler(stream=sys.stdout)
        logger = logging.getLogger(cls.__name__)

        if log_file:
            file_handler = logging.FileHandler(realpath(log_file), mode="w")

        return logger 

Example 12

def bro_server(bro_file, interface="eth0", bro_path="/usr/local/bro/bin/bro"):
    u""" 跑bro服务进程 """
    # 获取绝对路径
    bro_file = path.realpath(bro_file)
    http_file = "/usr/local/bro/share/bro/base/protocols/http/main.bro"
    bro_scripts = ' '.join([bro_file, http_file])

    cmd = "sudo {bro_path} -C -b -i {interface} {bro_scripts}"
    cmd = cmd.format(bro_path=bro_path,

    msg = "the cmd is: %s" % cmd

    # change pwd to /tmp
    tmp_dir = path.join(path.dirname(path.realpath(__file__)), '../../tmp/')

    result = run(cmd) 

Example 13

def ProcessFlags(env, flags):
    for f in flags:
        if f:

    # fix relative CPPPATH
    for i, p in enumerate(env.get("CPPPATH", [])):
        if isdir(p):
            env['CPPPATH'][i] = realpath(p)

    # Cancel any previous definition of name, either built in or
    # provided with a -D option // Issue #191
    undefines = [u for u in env.get("CCFLAGS", []) if u.startswith("-U")]
    if undefines:
        for undef in undefines:
        env.Append(_CPPDEFFLAGS=" %s" % " ".join(undefines)) 

Example 14

def _get_settings_helper(self):
        main_dir = path.dirname(path.realpath(__file__))
        main_dir = path.realpath(path.join(main_dir, '..', '..'))
        default_filepath = path.join(main_dir, 'default_settings.yml')
        user_filepath = path.join(main_dir, 'settings.yml')
        args = self._get_args()
        if args.settings_path:
            user_filepath = args.settings_path

        # open the default file and get version information
        with open(default_filepath) as default_filestream:
            default_filesettings = yaml.load(default_filestream)

        # FIXME: not used
        current_version = default_filesettings['version'].split('.') # flake8: noqa

        if path.exists(user_filepath):
            filepath = user_filepath
            filepath = default_filepath

        with open(filepath) as setting_file:
            self.settings = yaml.load(setting_file, _OrderedLoader)

        return SpecialDict(**self.settings) 

Example 15

def resolve_rpath(lib_path, rpaths):
    """ Return 'lib_path' with its '@rpath' resolved

    If the 'lib_path' doesn't have '@rpath' then it's returned as is.

    If 'lib_path' has '@rpath' then returns the first 'rpaths'/'lib_path'
    combination found.  If the library can't be found in 'rpaths' then a
    detailed warning is printed and 'lib_path' is returned as is.

    lib_path : str
        The path to a library file, which may or may not start with '@rpath'.
    rpaths : sequence of str
        A sequence of search paths, usually gotten from a call to 'get_rpaths'.

    lib_path : str
        A str with the resolved libraries realpath.
    if not lib_path.startswith('@rpath/'):
        return lib_path

    lib_rpath = lib_path.split('/', 1)[1]
    for rpath in rpaths:
        rpath_lib = realpath(pjoin(rpath, lib_rpath))
        if os.path.exists(rpath_lib):
            return rpath_lib

        "Couldn't find {0} on paths:\n\t{1}".format(
            '\n\t'.join(realpath(path) for path in rpaths),
    return lib_path 

Example 16

def wheel_libs(wheel_fname, filt_func=None):
    """ Return analysis of library dependencies with a Python wheel

    Use this routine for a dump of the dependency tree.

    wheel_fname : str
        Filename of wheel
    filt_func : None or callable, optional
        If None, inspect all files for library dependencies. If callable,
        accepts filename as argument, returns True if we should inspect the
        file, False otherwise.

    lib_dict : dict
        dictionary with (key, value) pairs of (''libpath'',
        ''dependings_dict'').  ''libpath'' is library being depended on,
        relative to wheel root path if within wheel tree.  ''dependings_dict''
        is (key, value) of (''depending_lib_path'', ''install_name'').  Again,
        ''depending_lib_path'' is library relative to wheel root path, if
        within wheel tree.
    with TemporaryDirectory() as tmpdir:
        zip2dir(wheel_fname, tmpdir)
        lib_dict = tree_libs(tmpdir, filt_func)
    return stripped_lib_dict(lib_dict, realpath(tmpdir) + os.path.sep)

Example 17

def main():
    parser = OptionParser(
        usage="%s WHEEL_OR_PATH_TO_ANALYZE\n\n" % sys.argv[0] + __doc__,
        version="%prog " + __version__)
        Option("-a", "--all",
               help="Show all dependencies, including system libs"),
        Option("-d", "--depending",
               help="Show libraries depending on dependencies")])
    (opts, paths) = parser.parse_args()
    if len(paths) < 1:

    multi = len(paths) > 1
    for path in paths:
        if multi:
            print(path + ':')
            indent = '   '
            indent = ''
        if isdir(path):
            lib_dict = tree_libs(path)
            lib_dict = stripped_lib_dict(lib_dict, realpath(getcwd()) + psep)
            lib_dict = wheel_libs(path)
        keys = sorted(lib_dict)
        if not opts.all:
            keys = [key for key in keys if filter_system_libs(key)]
        if not opts.depending:
            if len(keys):
                print(indent + ('\n' + indent).join(keys))
        i2 = indent + '    '
        for key in keys:
            print(indent + key + ':')
            libs = lib_dict[key]
            if len(libs):
                print(i2 + ('\n' + i2).join(libs)) 

Example 18

def test_given_directory():
    # Test InGivenDirectory
    cwd = getcwd()
    with InGivenDirectory() as tmpdir:
        assert_equal(tmpdir, abspath(cwd))
        assert_equal(tmpdir, abspath(getcwd()))
    with InGivenDirectory(MY_DIR) as tmpdir:
        assert_equal(tmpdir, MY_DIR)
        assert_equal(realpath(MY_DIR), realpath(abspath(getcwd())))
    # We were deleting the Given directory!  Check not so now.

Example 19

def decideClean(workDir, architecture, aggressiveCleanup):
  """ Decides what to delete, without actually doing it:
      - Find all the symlinks in "BUILD"
      - Find all the directories in "BUILD"
      - Schedule a directory for deletion if it does not have a symlink
  symlinksBuild = [os.readlink(x) for x in glob.glob("%s/BUILD/*-latest*" % workDir)]
  # $WORK_DIR/TMP should always be cleaned up. This does not happen only
  # in the case we run out of space while unpacking.
  # $WORK_DIR//store can be cleaned up as well, because
  # we do not need the actual tarballs after they have been built.
  toDelete = ["%s/TMP" % workDir]
  if aggressiveCleanup:
    toDelete += ["%s/TARS/%s/store" % (workDir, architecture),
                 "%s/SOURCES" % (workDir)]
  allBuildStuff = glob.glob("%s/BUILD/*" % workDir)
  toDelete += [x for x in allBuildStuff
               if not path.islink(x) and not basename(x) in symlinksBuild]
  installGlob ="%s/%s/*/" % (workDir, architecture)
  installedPackages = set([dirname(x) for x in glob.glob(installGlob)])
  symlinksInstall = []
  for x in installedPackages:
    symlinksInstall += [path.realpath(y) for y in glob.glob(x + "/latest*")]
  toDelete += [x for x in glob.glob(installGlob+ "*")
               if not path.islink(x) and not path.realpath(x) in symlinksInstall]
  toDelete = [x for x in toDelete if path.exists(x)]
  return toDelete 

Example 20

def _get_script_dir(follow_symlinks: bool = True) -> Path:
    # Getting the path to the trust stores is tricky due to subtle differences on OS X, Linux and Windows
    if getattr(sys, "frozen", False):
        # py2exe, PyInstaller, cx_Freeze
        path = Path(sys.executable).absolute()
        path = Path(inspect.getabsfile(_get_script_dir))
    if follow_symlinks:
        path = Path(realpath(path))
    return path.parent 


os.path.realpath() in Python is used to get the canonical path of a specified filename by removing any symlinks found in the path .

Syntax: os.path.realpath (path)

path : A path-like object representing the file system path.
A path-like object is either a string or bytes object representing a path.

Return Type: This method returns a string value which represents the canonical path.

Create soft link or symbolic link
On Unix or Linux, a soft link or symbolic link can be created using the ln command. Following is the syntax for creating a symbolic link on the command line:

 $ ln -s {source-filename} {symbolic-filename} 



In the above output, “/ home / ihritik / Desktop / file (shortcut) .txt " is a symbolic link.

Code: using os.path.realpath () method to get canonical path and resolution symbolic links.

# Python program to explain the os.path.realpath () method

# import of the os module

import os

# Path

path = "/ home / ihritik / Desktop / file (shortcut) .txt"


# Get the canonical path
# of the specified path
# by removing any symbolic links
# met on the way

real_path = os.path.realpath (path)

# Print the canonical path

print (real_path)


# Path

path = "/../../ GeeksForGeeks /"


# Get the canonical path
# of the specified path
# elimination of any symbolic links
# met in the path

real_path = os.path.realpath (path)

# Print the canonical path

print (real_path)


# Path

path = "file.txt"


# Get the canonical path
# specified path
# remove any symbolic links
# met on the way

real_path = os .path.realpath (path)

# Print the canonical path

print (real_path)


os.chdir ( " / home / ihritik / Downloads / " )


# Path

path = "file.txt"

# Get the canonical path
# of the specified path
# elimination of any symbolic links
# met in the path

real_path = os.path.realpath (path)

# Print the canonical path

print ( real_path)


 / home / ihritik / Documents / file (original) .txt /GeeksForGeeks/ /home/ihritik/file.txt /home/ihritik/Downloads/file.txt 

Link: https: / /

Python | os.path.realpath () method: StackOverflow Questions

Why would one use both, os.path.abspath and os.path.realpath?

In multiple open source projects, I have seen people do os.path.abspath(os.path.realpath(__file__)) to get the absolute path to the current file.

However, I find that os.path.abspath(__file__) and os.path.realpath(__file__) produce the same result. os.path.abspath(os.path.realpath(__file__)) seems to be a bit redundant.

Is there a reason people are using that?

Answer #1

Put this inside your package"s file:

# For relative imports to work in Python 3.6
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))

Assuming your package is like this:

├── project
│   ├── package
│   │   ├──
│   │   ├──
│   │   └──
│   └──

Now use regular imports in you package, like:

# in
from module1 import class1

This works in both python 2 and 3.

Answer #2

For your stated scenario, there is no reason to combine realpath and abspath, since os.path.realpath actually calls os.path.abspath before returning a result (I checked Python 2.5 to Python 3.6).

  • os.path.abspath returns the absolute path, but does NOT resolve symlinks in its argument.
  • os.path.realpath will first resolve any symbolic links in the path, and then return the absolute path.

However, if you expect your path to contain a ~, neither abspath or realpath will resolve ~ to the user"s home directory, and the resulting path will be invalid. You will need to use os.path.expanduser to resolve this to the user"s directory.

For the sake of a thorough explanation, here are some results which I"ve verified in Windows and Linux, in Python 3.4 and Python 2.6. The current directory (./) is my home directory, which looks like this:

|- data (symlink to /mnt/data)
|- subdir (extra directory, for verbose explanation)
# os.path.abspath returns the absolute path, but does NOT resolve symlinks in its argument

# os.path.realpath will resolve symlinks AND return an absolute path from a relative path

# NEITHER abspath or realpath will resolve or remove ~.


# And the returned path will be invalid

# Use realpath + expanduser to resolve ~

Answer #3

I had the exact same issue. If you are using a relative path os.path.dirname(path) will only return the relative path. os.path.realpath does the trick:

>>> import os
>>> f = open("file.txt")
>>> os.path.realpath(

Answer #4

For completeness" sake, I thought it would be worthwhile summarizing the various possible outcomes and supplying references for the exact behaviour of each.

The answer is composed of four sections:

  1. A list of different approaches that return the full path to the currently executing script.

  2. A caveat regarding handling of relative paths.

  3. A recommendation regarding handling of symbolic links.

  4. An account of a few methods that could be used to extract the actual file name, with or without its suffix, from the full file path.

Extracting the full file path

  • __file__ is the currently executing file, as detailed in the official documentation:

    __file__ is the pathname of the file from which the module was loaded, if it was loaded from a file. The __file__ attribute may be missing for certain types of modules, such as C modules that are statically linked into the interpreter; for extension modules loaded dynamically from a shared library, it is the pathname of the shared library file.

    From Python3.4 onwards, per issue 18416, __file__ is always an absolute path, unless the currently executing file is a script that has been executed directly (not via the interpreter with the -m command line option) using a relative path.

  • __main__.__file__ (requires importing __main__) simply accesses the aforementioned __file__ attribute of the main module, e.g. of the script that was invoked from the command line.

    From Python3.9 onwards, per issue 20443, the __file__ attribute of the __main__ module became an absolute path, rather than a relative path.

  • sys.argv[0] (requires importing sys) is the script name that was invoked from the command line, and might be an absolute path, as detailed in the official documentation:

    argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string "-c". If no script name was passed to the Python interpreter, argv[0] is the empty string.

    As mentioned in another answer to this question, Python scripts that were converted into stand-alone executable programs via tools such as py2exe or PyInstaller might not display the desired result when using this approach (i.e. sys.argv[0] would hold the name of the executable rather than the name of the main Python file within that executable).

  • If none of the aforementioned options seem to work, probably due to an atypical execution process or an irregular import operation, the inspect module might prove useful. In particular, invoking inspect.stack()[-1][1] should work, although it would raise an exception when running in an implementation without Python stack frame.

  • From Python3.6 onwards, and as detailed in another answer to this question, it"s possible to install an external open source library, lib_programname, which is tailored to provide a complete solution to this problem.

    This library iterates through all of the approaches listed above until a valid path is returned. If all of them fail, it raises an exception. It also tries to address various pitfalls, such as invocations via the pytest framework or the pydoc module.

    import lib_programname
    # this returns the fully resolved path to the launched python program
    path_to_program = lib_programname.get_path_executed_script()  # type: pathlib.Path

Handling relative paths

When dealing with an approach that happens to return a relative path, it might be tempting to invoke various path manipulation functions, such as os.path.abspath(...) or os.path.realpath(...) in order to extract the full or real path.

However, these methods rely on the current path in order to derive the full path. Thus, if a program first changes the current working directory, for example via os.chdir(...), and only then invokes these methods, they would return an incorrect path.

Handling symbolic links

If the current script is a symbolic link, then all of the above would return the path of the symbolic link rather than the path of the real file and os.path.realpath(...) should be invoked in order to extract the latter.

Further manipulations that extract the actual file name

os.path.basename(...) may be invoked on any of the above in order to extract the actual file name and os.path.splitext(...) may be invoked on the actual file name in order to truncate its suffix, as in os.path.splitext(os.path.basename(...)).

From Python 3.4 onwards, per PEP 428, the PurePath class of the pathlib module may be used as well on any of the above. Specifically, pathlib.PurePath(...).name extracts the actual file name and pathlib.PurePath(...).stem extracts the actual file name without its suffix.

Answer #5

Update 2018-11-28:

Here is a summary of experiments with Python 2 and 3. With - runs - runs lib/
lib/ - prints filepath expressions

| Python | Run statement       | Filepath expression                    |
|      2 | execfile            | os.path.abspath(inspect.stack()[0][1]) |
|      2 | from lib import bar | __file__                               |
|      3 | exec                | (wasn"t able to obtain it)             |
|      3 | import      | __file__                               |

For Python 2, it might be clearer to switch to packages so can use from lib import bar - just add empty files to the two folders.

For Python 3, execfile doesn"t exist - the nearest alternative is exec(open(<filename>).read()), though this affects the stack frames. It"s simplest to just use import foo and import - no files needed.

See also Difference between import and execfile

Original Answer:

Here is an experiment based on the answers in this thread - with Python 2.7.10 on Windows.

The stack-based ones are the only ones that seem to give reliable results. The last two have the shortest syntax, i.e. -

print os.path.abspath(inspect.stack()[0][1])                   #
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:filepathslib

Here"s to these being added to sys as functions! Credit to @Usagi and @pablog

Based on the following three files, and running from its folder with python (also tried execfiles with absolute paths and calling from a separate folder). execfile("") execfile("lib/")

import sys
import os
import inspect

print "Python " + sys.version

print __file__                                        #
print sys.argv[0]                                     #
print inspect.stack()[0][1]                           # lib/
print sys.path[0]                                     # C:filepaths

print os.path.realpath(__file__)                      #
print os.path.abspath(__file__)                       #
print os.path.basename(__file__)                      #
print os.path.basename(os.path.realpath(sys.argv[0])) #

print sys.path[0]                                     # C:filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0])  # C:filepaths
print os.path.dirname(os.path.abspath(__file__))      # C:filepaths
print os.path.dirname(os.path.realpath(sys.argv[0]))  # C:filepaths
print os.path.dirname(__file__)                       # (empty string)

print inspect.getfile(inspect.currentframe())         # lib/

print os.path.abspath(inspect.getfile(inspect.currentframe())) #
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:filepathslib

print os.path.abspath(inspect.stack()[0][1])          #
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:filepathslib

Answer #6

os.path.realpath derefences symbolic links on those operating systems which support them.

os.path.abspath simply removes things like . and .. from the path giving a full path from the root of the directory tree to the named file (or symlink)

For example, on Ubuntu

$ ls -l
total 0
-rw-rw-r-- 1 guest guest 0 Jun 16 08:36 a
lrwxrwxrwx 1 guest guest 1 Jun 16 08:36 b -> a

$ python
Python 2.7.11 (default, Dec 15 2015, 16:46:19) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.

>>> from os.path import abspath, realpath

>>> abspath("b")

>>> realpath("b")

Symlinks can contain relative paths, hence the need to use both. The inner call to realpath might return a path with embedded .. parts, which abspath then removes.

Answer #7

To get the full path to the directory a Python file is contained in, write this in that file:

import os 
dir_path = os.path.dirname(os.path.realpath(__file__))

(Note that the incantation above won"t work if you"ve already used os.chdir() to change your current working directory, since the value of the __file__ constant is relative to the current working directory and is not changed by an os.chdir() call.)

To get the current working directory use

import os
cwd = os.getcwd()

Documentation references for the modules, constants and functions used above:

Answer #8

You need to call os.path.realpath on __file__, so that when __file__ is a filename without the path you still get the dir path:

import os

Answer #9

unfortunately, this module needs to be inside the package, and it also needs to be runnable as a script, sometimes. Any idea how I could achieve that?

It"s quite common to have a layout like this...

...with a like this...

#!/usr/bin/env python3

# Exported function
def as_int(a):
    return int(a)

# Test function for module  
def _test():
    assert as_int("1") == 1

if __name__ == "__main__":

...a like this...

#!/usr/bin/env python3

from .mymodule import as_int

# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add("1", "1") == 2

if __name__ == "__main__":

...and a like this...

#!/usr/bin/env python3

from mypackage.myothermodule import add

def main():
    print(add("1", "1"))

if __name__ == "__main__":

...which works fine when you run or mypackage/, but fails with mypackage/, due to the relative import...

from .mymodule import as_int

The way you"re supposed to run it is...

python3 -m mypackage.myothermodule

...but it"s somewhat verbose, and doesn"t mix well with a shebang line like #!/usr/bin/env python3.

The simplest fix for this case, assuming the name mymodule is globally unique, would be to avoid using relative imports, and just use...

from mymodule import as_int

...although, if it"s not unique, or your package structure is more complex, you"ll need to include the directory containing your package directory in PYTHONPATH, and do it like this...

from mypackage.mymodule import as_int

...or if you want it to work "out of the box", you can frob the PYTHONPATH in code first with this...

import sys
import os

SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))

from mypackage.mymodule import as_int

It"s kind of a pain, but there"s a clue as to why in an email written by a certain Guido van Rossum...

I"m -1 on this and on any other proposed twiddlings of the __main__ machinery. The only use case seems to be running scripts that happen to be living inside a module"s directory, which I"ve always seen as an antipattern. To make me change my mind you"d have to convince me that it isn"t.

Whether running scripts inside a package is an antipattern or not is subjective, but personally I find it really useful in a package I have which contains some custom wxPython widgets, so I can run the script for any of the source files to display a wx.Frame containing only that widget for testing purposes.

Answer #10


as others have said. You may also want to use os.path.realpath to eliminate symlinks:

import os