0
|-- eval.py
|-- modeling_llama.py
|-- patch
|   |-- __init__.py
|   |-- flash_attn.py
|   |-- log_scale.py
|   |-- ntk.py
|   |-- ntk_fixed.py
|   |-- ntk_mixed.py
|   `-- rerope.py
|-- prompt.py
|-- test_model.sh
`-- utils.py

Above is my project directory.

The script I run is eval.py, which imports utils.py. patch is imported to utils.py. patch.rerope depends on modelling_llama, so I have to import modelling_llama in rerope. I'm confused about how I can correctly import modelling_llama in rerope since it's a repository level higher.

Should I be import modelling_llama, from .. import modelling_llama, or import ..modeling_llama.

I've tried all the above and found merely import modelling_llama work fine for me, but I'm still wondering why.

Arist12
  • 172
  • 1
  • 7

3 Answers3

3

Relative imports only make sense within a package. This can be confusing if you think you have your code in a package, but the Python interpreter doesn't see it that way.

In your current project, Python sees eval, modeling_llama, util and the other top-level things in your file structure are seen as top level modules. This happens because of how you're running your script. The top-level folder is getting added to sys.path (as is explained by one of the quotes you have in your answer). If you think these should be in a package (named after whatever the top-level folder is named), you need to run your code from one folder further up (with python -m my_package.eval perhaps).

If both modeling_llama and patch.rerope are part of the same top-level package (with patch being a sub-package), then you can use the relative import you were trying out. This will require you to change all your other import statements too, as import util won't work from eval if they're both in a package (and thus not accessible as top-level module names). If modeling_llama really should be a top-level module, then you must import it as such, with import modeling_llama (or from modeling_llama import whatever, if you don't need a reference to the module itself).

Blckknght
  • 100,903
  • 11
  • 120
  • 169
0

I went through several questions regarding relative import or python-import, all of them provided useful information, but none of them gave me a clear whole picture of how to use python-import.

After reading Python documentation and related PEP, and doing some necessary experiments, I think I've got a clear picture of this issue. While I may still miss some corner cases, I share my findings here and hope it's useful.

Import convention

Before we dive into details, let's first classify python-import.

All import statements are absolute import by default.

Only special syntax (leading dots, e.g. from ..modelling_llama import module_x) leads to relative imports.

Absolute Imports

Absolute imports search from sys.path.

Which is initialized upon program startup, a potentially unsafe path is prepended to it:

  • python -m module command line: prepend the current working directory.
  • python script.py command line: prepend the script’s directory. If it’s a symbolic link, resolve symbolic links.
  • python -c code and python (REPL) command lines: prepend an empty string, which means the current working directory.

This paragraph is from Python Documentation, but it only talks about how sys.path is initialized. But how will sys.path change for each imported file? After simple experiments, I've come to the conclusion that except for the main script whose sys.path is initialized the way above, all the subsequent imported modules will inherit this sys.path and only look for packages from this path.

This perfectly answers my question of why merely import modelling_llama works well.

Relative Imports

Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy.

For how to determine the __name__ attribute, Relative imports for the billionth time is quite clear.

In short:

  • If it was loaded as the top-level script, its name is __main__.
  • If it was loaded as a module, its name is [the filename, preceded by the names of any packages/subpackages of which it is a part, separated by dots], for example, package.subpackage1.moduleX.

This again perfectly explains why from ..modeling_llama import module_x will fail. Since the name of this rerope module is patch.rerope, .. will lead to beyond top level package error in relative import, which makes sense.

So what if I insisted on using relative imports? Adding another folder level to match .. should work fine!

Arist12
  • 172
  • 1
  • 7
-1

you should add the directory path to environment

use this codes

rerope.py

import os
abspath = os.path.abspath(__file__)
filename = os.sep.join(abspath.split(os.sep)[-2:])
abspath = abspath.replace(filename, "")
import sys
sys.path.append(abspath)

import modelling_llama

eval.py

import os
abspath = os.path.abspath(__file__)
filename = abspath.split(os.sep)[-1]
abspath = abspath.replace(filename, "")
import sys
sys.path.append(abspath)

import modelling_llama
Jiu_Zou
  • 463
  • 1
  • 4