从不同文件夹导入文件

问:

我有以下文件夹结构:

application
├── app
│   └── folder
│       └── file.py
└── app2
    └── some_folder
        └── some_file.py

从 some_file.py 内部,如何从 file.py 导入函数?

我试过了:

from application.app.folder.file import func_name

答1:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

注意:此答案旨在解决一个非常具体的问题。对于大多数从搜索引擎来到这里的程序员来说,这不是您要寻找的答案。通常,您会将文件构造成包(请参阅其他答案),而不是修改搜索路径。

默认情况下,您不能。导入文件时,Python 仅搜索运行入口点脚本的目录和 sys.path,其中包括包安装目录等位置(实际上是 a little more complex,但大多数情况下都如此)。

但是,您可以在运行时添加到 Python 路径:

# some_file.py
import sys
# insert at 1, 0 is the script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')

import file

sys.path.append('/path/to/application/app/folder') 更干净 imo

@pseudosudo:是的,是的,但是在开头插入它的好处是,在命名冲突的情况下,可以保证在其他路径(甚至是内置路径)之前搜索路径。

@kreativitea - sys.path 返回 list,而不是 deque,将 list 转换为 deque 并返回是愚蠢的。

它是否被认为是一种管理文件夹中 .py 文件的 Pythonic 方式?我想知道...为什么默认情况下不支持它?将所有 .py 文件保存在一个目录中是没有意义的。

@Ofir:不,这不是一个干净的pythonic 解决方案。通常,您应该使用包(基于目录树)。这个答案是针对所提出的问题的,并且由于某种原因继续获得大量支持。

答2:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

没有错:

from application.app.folder.file import func_name

只需确保 folder 还包含一个 init.py,这样就可以将其作为一个包包含在内。不知道为什么其他答案谈论PYTHONPATH。

因为这不包括需要修改 PYTHONPATH 的情况。假设您在同一级别上有两个文件夹:A 和 B。 A 有一个 __init.py__。尝试从 A 中的 B 导入某些内容。

init.py 或 __init__.py 文件中有什么内容?

@Xinyang 它可以是一个空文件。它的存在告诉 Python 将目录视为一个包。

这不是目前投票率最高的答案,但它是最正确的答案(对于大多数情况)。只需创建一个包。这并不难。需要其他答案,因为有时您可能会受到某些系统更改(创建或修改文件等)的限制,例如在测试期间。

无论我尝试什么,这都行不通。我想从“兄弟”目录导入,所以一个上一个下。都有 __ init __.py,包括父级。这是 python 3 特定的吗?

答3:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

当模块位于并行位置时,如问题所示:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

此简写使一个模块对另一个模块可见:

import sys
sys.path.append('../')

作为警告:只要导入脚本是从其包含目录运行的,它就可以工作。否则,运行脚本的任何其他目录的父目录都将附加到路径中,并且导入将失败。

为避免这种情况,我们可以获取文件 sys.path.append(os.path.dirname(os.path.abspath(__file__))) 的父目录

这对我不起作用 - 我必须在其中添加一个额外的目录名才能爬回父级,以便从命令行运行 cli/foo.py 能够import cli.bar

@Rahul,您的解决方案不适用于交互式外壳

如果您从根文件夹(即应用程序文件夹)运行它,您可能对 sys.path.append('.') 没问题,然后使用 from app2.some_folder.some_file import your_function 导入模块。或者,对我有用的是从根文件夹运行 python3 -m app2.another_folder.another_file。

答4:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

首先在 name-file.py 中导入 sys

 import sys

其次在 name-file.py 中附加文件夹路径

sys.path.insert(0, '/the/folder/path/name-package/')

第三 在您的子目录中创建一个名为 __ init __.py 的空白文件(这告诉 Python 它是一个包)

名称文件.py

名称包 __ 初始化 __.py 名称模块.py

__ 初始化 __.py

名称-module.py

四、在name-file.py文件夹内导入模块

from name-package import name-module

由于 name-folder 位于 name-file.py 的正下方,即使没有 sys.path.insert-command,这也应该可以工作。因此,答案留下了问题,即使名称文件夹位于任意位置,此解决方案是否也有效。

你是说我必须硬编码脚本的路径吗?这意味着该解决方案不可移植。另外问题是如何从一个子文件夹访问另一个子文件夹。为什么不遵循原始问题的名称约定和文件结构?

@Giacomo您不必对任何内容进行硬编码。只需将其作为参数传递给脚本。

答5:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

我认为一种特别的方法是使用文档中描述的 the environment variable PYTHONPATH:Python2、Python3

# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%

等等,我会用文件名替换 myScripts 吗?

不,使用 .py 文件的目录路径

不幸的是,如果您使用的是 Anaconda,这将不起作用,因为在内部 PYTHONPATH 并没有真正使用!

对于 anaconda 的(最近)更改,请参阅此 SO 以了解工作流程和解决方法的评论:stackoverflow.com/questions/17386880/… 一般来说,构建和安装小包而不是破解导入目录。

答6:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

您的问题是 Python 正在 Python 目录中查找此文件,但没有找到它。您必须指定您正在谈论的是您所在的目录,而不是 Python 目录。

为此,您需要更改:

from application.app.folder.file import func_name

对此:

from .application.app.folder.file import func_name

通过添加点,您要在此文件夹中查找应用程序文件夹,而不是在 Python 目录中查找。

ImportError: 尝试在没有已知父包的情况下进行相对导入 :(

我遇到了同样的错误,有什么解决办法吗?

答7:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

这里的答案不够清晰,这是在 Python 3.6 上测试的

使用此文件夹结构:

main.py
|
---- myfolder/myfile.py

myfile.py 包含以下内容:

def myfunc():
    print('hello')

main.py 中的导入语句是:

from myfolder.myfile import myfunc
myfunc()

这将打印你好。

在 myfolder 中添加一个 init.py(空)配置文件在 linux 上对我有用(y)

@Vincent 你是说__init__.py吗?

由于某种原因,添加 __init__.py 对我不起作用。我在 Ubuntu 18 上使用 Py 3.6.5。它适用于 Pycharm,但不适用于终端

这与询问从文件树的不同分支而不是当前工作目录导入文件的问题完全无关。

可爱的图表明确忽略了 OP 的问题。

答8:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

在 Python 3.4 及更高版本中,您可以import from a source file directly (link to documentation)。这不是最简单的解决方案,但为了完整起见,我将这个答案包括在内。

这是一个例子。首先,要导入的文件,名为 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()

输出:


['__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()

输出:


['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!

以编程方式导入模块是在 Python 3.1 中引入的,让您可以更好地控制模块的导入方式。有关详细信息,请参阅文档。

我不知道是否有人试图理解这一点,但我认为这太复杂了。

这是唯一对我有用的解决方案。我在不同的目录中有相同的文件名。

如何导入文件中的所有内容?

那是唯一对我有用的解决方案。

答9:

huntsbot.com – 高效赚钱,自由工作

尝试 Python 的相对导入:

from ...app.folder.file import func_name

每个前导点都是从当前目录开始的层次结构中的另一个更高级别。

问题?如果这对您不起作用,那么您可能会被许多 gotcha 的相对导入所吸引。阅读答案和评论以了解更多详情:How to fix “Attempted relative import in non-package” even with init.py

提示:在每个目录级别都有 init.py。您可能需要从顶级目录运行的 python -m application.app2.some_folder.some_file(不包括 .py),或者在 PYTHONPATH 中有该顶级目录。 呼!

如果您的目录名称以数字开头(例如,不允许使用 import ..70_foo.test),这似乎不起作用

哇,这确实有效。我不知道你可以通过使用多个点来“向上”一个目录。

答10:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

据我所知,直接在要导入的函数的文件夹中添加一个 init.py 文件就可以了。

仅当想要包含该其他目录的脚本已在 sys.path 中时

`我在 Windows 上使用了 sys.path.append(tools_dir),不需要添加 init.py’ file in my directory tools_dir``

答11:

huntsbot.com – 高效赚钱,自由工作

将应用程序移动到其他环境时,将 sys.path.append 与绝对路径一起使用并不理想。使用相对路径并不总是有效,因为当前工作目录取决于脚本的调用方式。

由于应用程序文件夹结构是固定的,我们可以使用 os.path 来获取我们希望导入的模块的完整路径。例如,如果这是结构:

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py

假设您要导入 mango 模块。您可以在 vanilla.py 中执行以下操作:

import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango

当然,您不需要 mango_dir 变量。

要了解其工作原理,请查看此交互式会话示例:

>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
    '/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>> 
>>> newdir
'/home/me/application/app2/another_folder'
>>> 

并查看 os.path 文档。

还值得注意的是,使用 packages 时处理多个文件夹会更容易,因为可以使用带点的模块名称。

原文链接:https://www.huntsbot.com/qa/7Q0e/importing-files-from-different-folder?lang=zh_CN&from=csdn

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值