我有这样的文件夹结构:
application
├── app
│ └── folder
│ └── file.py
└── app2
└── some_folder
└── some_file.py
如何从file.py或some_file.py中导入函数?我尝试了:
from application.app.folder.file import func_name
但它不起作用。
我有这样的文件夹结构:
application
├── app
│ └── folder
│ └── file.py
└── app2
└── some_folder
└── some_file.py
如何从file.py或some_file.py中导入函数?我尝试了:
from application.app.folder.file import func_name
但它不起作用。
当前回答
哇,我没想到会花这么多时间在这上面。以下内容对我有用:
操作系统:Windows 10
Python:v3.10.0
注意:由于我是Python v3.10.0,所以我没有使用__init__.py文件,这对我来说无论如何都不起作用。
application
├── app
│ └── folder
│ └── file.py
└── app2
└── some_folder
└── some_file.py
王旭的第一个解决方案对我有效。为了清楚起见,我将其转发了一个绝对的文件参考:
import sys
sys.path.insert(1, 'C:\\Users\\<Your Username>\\application')
import app2.some_folder.some_file
some_file.hello_world()
替代解决方案:然而,这也对我有效:
import sys
sys.path.append( '.' )
import app2.some_folder.some_file
some_file.hello_world()
虽然,我不明白为什么它会起作用。我以为点是对当前目录的引用。但是,当打印出当前文件夹的路径时,当前目录已列在顶部:
for path in sys.path:
print(path)
希望有人能在评论中澄清为什么这样做有效。尽管如此,我也希望它能帮助一些人。
其他回答
├───root
│ ├───dir_a
│ │ ├───file_a.py
│ │ └───file_xx.py
│ ├───dir_b
│ │ ├───file_b.py
│ │ └───file_yy.py
│ ├───dir_c
│ └───dir_n
您可以将父目录添加到PYTHONPATH,为了实现这一点,您可以在sys.path中列出的“模块搜索路径”中使用依赖于操作系统的路径。因此,您可以像下面这样轻松地添加父目录:
# file_b.py
import sys
sys.path.insert(0, '..')
from dir_a.file_a import func_name
尝试Python的相对导入:
from ...app.folder.file import func_name
每个前导点都是从当前目录开始的层次结构中的另一个更高级别。
问题?如果这对你不起作用,那么你可能会被许多gotcha的相对进口产品所蚕食。阅读答案和评论以了解更多详细信息:如何修复“尝试在非包中进行相对导入”,即使使用__init__.py
提示:在每个目录级别都有__init__.py。您可能需要python-m application.app2.some_folder.some_file(去掉.py),它可以从顶层目录运行,也可以在PYTHONPATH中包含该顶层目录。呸!
我也面临着同样的挑战,尤其是在导入多个文件时,这就是我如何克服的。
import os, sys
from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))
from root_folder import file_name
这里的答案不够清晰,这是在Python 3.6上测试的
使用此文件夹结构:
main.py
|
---- myfolder/myfile.py
其中myfile.py包含内容:
def myfunc():
print('hello')
main.py中的import语句是:
from myfolder.myfile import myfunc
myfunc()
这将打印hello。
在Python 3.4及更高版本中,您可以直接从源文件导入(链接到文档)。这不是最简单的解决方案,但为了完整起见,我将此答案包括在内。
这里有一个例子。首先,要导入的文件名为foo.py:
def announce():
print("Imported!")
导入上述文件的代码深受文档中示例的启发:
import importlib.util
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
foo = module_from_file("foo", "/path/to/foo.py")
if __name__ == "__main__":
print(foo)
print(dir(foo))
foo.announce()
输出:
<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
请注意,变量名、模块名和文件名不必匹配。此代码仍然有效:
import importlib.util
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
baz = module_from_file("bar", "/path/to/foo.py")
if __name__ == "__main__":
print(baz)
print(dir(baz))
baz.announce()
输出:
<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
Python 3.1中引入了以编程方式导入模块,使您能够更好地控制模块的导入方式。有关更多信息,请参阅文档。