Import a Module from a Relative Path

relative path in Import-Module

When you use a relative path, it is based off the currently location (obtained via Get-Location) and not the location of the script. Try this instead:

$ScriptDir = Split-Path -parent $MyInvocation.MyCommand.Path
Import-Module $ScriptDir\..\MasterScript\Script.ps1

In PowerShell v3, you can use the automatic variable $PSScriptRoot in scripts to simplify this to:

# PowerShell v3 or higher

#requires -Version 3.0
Import-Module $PSScriptRoot\..\MasterScript\Script.ps1

Import a module from a relative path

Assuming that both your directories are real Python packages (do have the __init__.py file inside them), here is a safe solution for inclusion of modules relatively to the location of the script.

I assume that you want to do this, because you need to include a set of modules with your script. I use this in production in several products and works in many special scenarios like: scripts called from another directory or executed with python execute instead of opening a new interpreter.

 import os, sys, inspect
# realpath() will make your script run, even if you symlink it :)
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if cmd_folder not in sys.path:
sys.path.insert(0, cmd_folder)

# Use this if you want to include modules from a subfolder
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)

# Info:
# cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!
# __file__ fails if the script is called in different ways on Windows.
# __file__ fails if someone does os.chdir() before.
# sys.argv[0] also fails, because it doesn't not always contains the path.

As a bonus, this approach does let you force Python to use your module instead of the ones installed on the system.

Warning! I don't really know what is happening when current module is inside an egg file. It probably fails too.

Importing from a relative path in Python

EDIT Nov 2014 (3 years later):

Python 2.6 and 3.x supports proper relative imports, where you can avoid doing anything hacky. With this method, you know you are getting a relative import rather than an absolute import. The '..' means, go to the directory above me:

from ..Common import Common

As a caveat, this will only work if you run your python as a module, from outside of the package. For example:

python -m Proj

Original hacky way

This method is still commonly used in some situations, where you aren't actually ever 'installing' your package. For example, it's popular with Django users.

You can add Common/ to your sys.path (the list of paths python looks at to import things):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common

os.path.dirname(__file__) just gives you the directory that your current python file is in, and then we navigate to 'Common/' the directory and import 'Common' the module.

Importing modules from parent folder

It seems that the problem is not related to the module being in a parent directory or anything like that.

You need to add the directory that contains ptdraft to PYTHONPATH

You said that import nib worked with you, that probably means that you added ptdraft itself (not its parent) to PYTHONPATH.

Get Path of File Relative Path of File that Imported Module in Python

Given the following file hierarchy :

stack_overflow/
├─ q67993523/
├─ my_module/
│ ├─ __init__.py
├─ 67993523.py
├─ hi.txt

With the following file content :

# 67993523.py
from my_module import do_stuff_with_file

do_stuff_with_file("hi.txt")
# my_module/__init__.py
def do_stuff_with_file(filename):
print(f"{filename!s} content is :")
with open(filename, "rt") as file:
print(file.read())

and the file hi.txt :

Hello !

When I run C:\path\to\python.exe C:/stack_overflow/q67993523/67993523.py (with the path to q67993523 included in my PYTHONPATH), with my current directory being q67993523/, I get :

hi.txt content is :
Hello !

But if I change my current dir to q67993523/my_module/ and execute the exact same command, I get :

hi.txt content is :
Traceback:
[...]
FileNotFoundError: [Errno 2] No such file or directory: 'hi.txt'

because relative to the current working directory q67993523/my_module/ there is no file hi.txt, the file would be ../hi.txt.

I think what you are doing is an instance of the XY problem.

What you are trying to achieve is to find a file given its name but not the location. It is very difficult to do, prone to error, and would include lots of hacks to work.

I don't think it is actually what you want to do. What you want to do, I presume, is not to search for files but just to use them. So you should not lose the precious information of their location.

For example, in your main script (mine is 67993523.py), you know that the file is right there, in the same directory. But if you just send hi.txt, because the function don't know the file location of the code that called her, it does not know where to search for the file.

Instead, give the complete file location, namely the absolute path.

If I change my main script to :

# 67993523.py
from pathlib import Path

from my_module import do_stuff_with_file

the_directory_of_this_pyfile = Path(__file__).parent
do_stuff_with_file((the_directory_of_this_pyfile / "hi.txt").absolute())

And run it with my current directory being q67993523/, I get :

C:\stack_overflow\q67993523\hi.txt content is :
Hello !

And when I change my current directory to q67993523/my_module/, I get the same thing :

C:\stack_overflow\q67993523\hi.txt content is :
Hello !

The difference is that in your script, the hi.txt filename assumes that your current working directory is q67993523/. If you have a different current working directory (because Pytest, because running the script for anywhere you want, ... see the comment from @tdelaney) then there is no ./hi.txt file, so it will fail.

I encourage you to learn on the topic of current working directory
and how to express the current Python file directory.

How to resolve relative import

You can try any one of these ways -

  1. Use absolute import
  2. Use standard way of import and remove from keyword
    Example: import main_script.function1
  3. Put this inside your package's init.py -
    For relative imports to work in Python 3.6 -
    import os, sys; sys.path.append(os.path.dirname(os.path.realpath(file)))
    And now use normal import statement like :
    from main_script import function1

Reference Attached

Do let me know if this helps out.
Happy Learning!!



Related Topics



Leave a reply



Submit