从不同文件夹导入文件

2024-11-18 08:41:00
admin
原创
12
摘要:问题描述:我有这个文件夹结构:application ├── app │   └── folder │   └── file.py └── app2 └── some_folder └── some_file.py 如何从file.py中导入函数some_file.py?我试过...

问题描述:

我有这个文件夹结构:

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

如何从file.py中导入函数some_file.py?我试过:

from application.app.folder.file import func_name

但它不起作用。


解决方案 1:

注意:这个答案是针对一个非常具体的问题。对于大多数通过搜索引擎来到这里的程序员来说,这不是你要找的答案。通常,你会将文件结构化为包(参见其他答案),而不是修改搜索路径。


默认情况下,您不能这样做。导入文件时,Python 仅搜索入口点脚本正在运行的目录,sys.path其中包括包安装目录等位置(实际上比这稍微复杂一些,但这涵盖了大多数情况)。

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

# some_file.py
import sys
# caution: path[0] is reserved for script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')

import file

解决方案 2:

以下做法没有错:

from application.app.folder.file import func_name

只需确保folder还包含__init__.py。这样就可以将其作为包包含在内。我不确定为什么其他答案会谈论PYTHONPATH

解决方案 3:

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

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

这种简写使得一个模块对另一个模块可见:

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

解决方案 4:

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

 import sys

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

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

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

  • 名称文件.py

  • 名称包

+ __ 初始化 __.py
+ 名称-模块.py

第四步,导入name-file.py文件夹中的模块

from name-package import name-module

解决方案 5:

尝试 Python 的相对导入:

from ...app.folder.file import func_name

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


有问题?如果这对你不起作用,那么你可能被相对导入的许多问题困扰了。阅读答案和评论以了解更多详细信息:
如何修复“尝试在非包中进行相对导入”,即使使用 __init__.py

提示:__init__.py每个目录级别都有。您可能需要python -m application.app2.some_folder.some_file(省略 .py)从顶级目录运行,或者将顶级目录放在 PYTHONPATH 中。呼!

解决方案 6:

我认为一个临时的方法是使用文档中描述的环境变量: PYTHONPATHPython2,Python3

# Linux and OS X
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH

# Windows
set PYTHONPATH=C:path    odirWithScripts;%PYTHONPATH%

解决方案 7:

问题是 Python 在错误的目录中查找文件。要解决这个问题,请尝试使用相对导入。更改

from application.app.folder.file import func_name

到:

from .application.app.folder.file import func_name

添加点指示 Python 在当前文件夹中查找application文件夹,而不是在 Python 安装文件夹中。

解决方案 8:

给定一个文件夹结构

├── main.py
└── myfolder
    └── myfile.py

其中myfile.py包含

def myfunc():
    print('hello')

要从 调用myfuncmain.py请使用:

from myfolder.myfile import myfunc
myfunc()

解决方案 9:

在 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 引入了以编程方式导入模块的功能,让您可以更好地控制模块的导入方式。请参阅文档了解更多信息。

解决方案 10:

当将应用程序移至其他环境时,使用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文档。

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

解决方案 11:

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

解决方案 12:

我面临着同样的挑战,特别是在导入多个文件时,这就是我设法克服它的方法。

import os, sys

from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))

from root_folder import file_name

解决方案 13:

这在 Linux 上的 Python 3 中对我有用:

import sys
sys.path.append(pathToFolderContainingScripts)
from scriptName import functionName #scriptName without .py extension

解决方案 14:

将其视为applicationPython 项目的根目录,__init__.pyapplicationappfolder文件夹中创建一个空文件。然后在 中some_file.py进行如下更改以获取func_name的定义:

import sys
sys.path.insert(0, r'/from/root/directory/application')

from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()

解决方案 15:

├───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

解决方案 16:

一种方法是创建一个包并使用绝对导入从包访问其他模块。从包根目录的脚本启动程序。此结构允许使用和访问子包、父包以及兄弟包和模块。

例如,尝试创建以下文件夹结构:

package/
├── __init__.py
├── main_module.py
├── module_0.py
├── subpackage_1/
|   ├── __init__.py
|   ├── module_1.py
|   └── sub_subpackage_3/
|       ├── __init__.py
|       └── module_3.py
└── subpackage_2/
    ├── __init__.py
    └── module_2.py

内容main_module.py

import subpackage_1.module_1

内容module_0.py

print('module_0 at parent directory, is imported')

内容module_1.py

print('importing other modules from module_1...')
import module_0
import subpackage_2.module_2
import subpackage_1.sub_subpackage_3.module_3

内容module_2.py

print('module_2 at same level directory, is imported')

内容module_3.py

print('module_3 at sub directory, is imported')

将所有__init__.py文件留空。

现在运行main_module.py;输出将是

importing other modules from module_1...
module_0 at parent directory, is imported
module_2 at same level directory, is imported
module_3 at sub directory, is imported

解决方案 17:

在我的例子中,我有一个要导入的类。我的文件如下所示:

# /opt/path/to/code/log_helper.py
class LogHelper:
    # stuff here

在我的主文件中,我通过以下方式包含了代码:

import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper

解决方案 18:

这在 Windows 上对我有用:

# some_file.py on mainApp/app2
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file

解决方案 19:

我多次遇到同样的问题,所以我想分享我的解决方案。

Python 版本:3.X

以下解决方案适用于使用 Python 版本 3.X 开发应用程序的人,因为自 2020 年 1 月 1 日起不再支持 Python 2。

项目结构

__init__.py在 Python 3 中,由于隐式命名空间 Packages 的存在,你不需要在项目子目录中使用。请参阅Python 3.3+ 中的包是否不需要init.py

Project 
├── main.py
├── .gitignore
|
├── a
|   └── file_a.py
|
└── b
    └── file_b.py

问题陈述

在中file_b.py,我想导入文件夹a下A的一个类。file_a.py

解决方案

1 一种快速但肮脏的方法

无需安装软件包,就像你目前正在开发一个新项目一样

使用try catch来检查是否有错误。代码示例:

import sys
try:
    # The insertion index should be 1 because index 0 is this file
    sys.path.insert(1, '/absolute/path/to/folder/a')  # the type of path is string
    # because the system path already have the absolute path to folder a
    # so it can recognize file_a.py while searching 
    from file_a import A
except (ModuleNotFoundError, ImportError) as e:
    print("{} fileure".format(type(e)))
else:
    print("Import succeeded")

2 安装你的包

安装应用程序后(本文不包含安装教程)

您可以简单地

try:
    from __future__ import absolute_import
    # now it can reach class A of file_a.py in folder a 
    # by relative import
    from ..a.file_a import A  
except (ModuleNotFoundError, ImportError) as e:
    print("{} fileure".format(type(e)))
else:
    print("Import succeeded")

祝你编码愉快!

解决方案 20:

我很特别:我在 Windows 上使用 Python!

我只是完成了信息:对于 Windows 和 Linux,相对路径和绝对路径都可以使用sys.path(我需要相对路径,因为我在几台 PC 上和不同的主目录下使用我的脚本)。

而在 Windows 中,和都`/`可以用作文件名的分隔符,当然,你必须将其转换为 Python 字符串。以下是一些有效示例:

sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')

(注意:我认为/比更方便``,即使它不那么“Windows 原生”,因为它与 Linux 兼容,并且更容易编写和复制到Windows 资源管理器)

解决方案 21:

以下对我有用:

操作系统:Windows 10

Python:v3.10.0

注意:由于我是 Python v3.10.0,所以我没有使用__init__.py文件,因为对我来说文件不起作用。

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

WY Hsu 的第一个解决方案对我有用。为了清楚起见,我重新发布了它并附上了绝对文件引用

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)

解决方案 22:

不要只做一个import ...,而是这样做:

from <MySubFolder> import <MyFile>

MyFile 位于 MySubFolder 内。

解决方案 23:

已经有许多其他解决方案了,但这是我的一点看法。假设您不想执行以下任何操作:

  • 添加__init__.py文件

  • 运行python -m mymodule

  • 编辑 __package__

  • 添加if签到__main__

  • sys.path手工编辑

  • 编辑PYTHONPATH

  • 重组项目

您可以使用一个工具,该工具会将给定的绝对/相对路径添加到 sys.path,同时确保该路径有效且格式正确。

$ pip install importmonkey[ github ] [ pip ]

# Example structure
├─ src
│   └─ project
│       ├─ __init__.py
│       └─ module.py
└─ test
    └─ test.py
# Example solution using the tool, in test.py

from importmonkey import add_path
add_path("../src")  # relative to current __file__
import project

# You can add as many paths as needed, absolute or relative, in any file.
# Relative paths start from the current __file__ directory.
# Normal unix path conventions work so you can use '..' and '.' and so on.
# The paths you try to add are checked for validity etc. help(add_path) for details.

隶属关系披露:我制作了 importmonkey。

解决方案 24:

我正在开发一个项目a,希望用户pip install a通过以下文件列表进行安装:

.
├── setup.py
├── MANIFEST.in
└── a
    ├── __init__.py
    ├── a.py
    └── b
        ├── __init__.py
        └── b.py

设置.py

from setuptools import setup

setup (
  name='a',
  version='0.0.1',
  packages=['a'],
  package_data={
    'a': ['b/*'],
  },
)

清单

recursive-include b *.*

一个/初始化.py

from __future__ import absolute_import

from a.a import cats
import a.b

一个/一个.py

cats = 0

a/b/初始化.py

from __future__ import absolute_import

from a.b.b import dogs

a/b/b.py

dogs = 1

我通过从目录运行以下命令安装了该模块MANIFEST.in

python setup.py install

/moustache/armwrestle然后,我可以从文件系统上完全不同的位置运行:

import a
dir(a)

这证实了a.cats确实等于 0,也a.b.dogs确实等于 1,正如预期的那样。

解决方案 25:

我的解决方案是针对那些包中已经有所有必需文件__init__.py,但导入仍然不起作用的人。

import sys
import os
sys.path.insert(0, os.getcwd())

import application.app.folder.file as file

解决方案 26:

下面的代码以 Python 版本安全的方式导入由其路径给出的 Python 脚本,无论它位于何处:

def import_module_by_path(path):
    name = os.path.splitext(os.path.basename(path))[0]
    if sys.version_info[0] == 2:
        # Python 2
        import imp
        return imp.load_source(name, path)
    elif sys.version_info[:2] <= (3, 4):
        # Python 3, version <= 3.4
        from importlib.machinery import SourceFileLoader
        return SourceFileLoader(name, path).load_module()
    else:
        # Python 3, after 3.4
        import importlib.util
        spec = importlib.util.spec_from_file_location(name, path)
        mod = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(mod)
        return mod

我在psutils的代码库中的第 1042 行发现了这一点psutils.test.__init__.py截至 2020 年 10 月 9 日的最新提交)。

使用示例:

script = "/home/username/Documents/some_script.py"
some_module = import_module_by_path(script)
print(some_module.foo())

重要警告:该模块将被视为顶级;其中来自父包的任何相对导入都将失败。

解决方案 27:

这对我有用。

Python 会将包含你启动的脚本的文件夹添加到 PYTHONPATH,因此如果你运行

python application/app2/some_folder/some_file.py

仅将文件夹 application/app2/some_folder 添加到路径中(而不是在其中执行命令的基本目录)。相反,将您的文件作为模块运行,并在您的 some_folder 目录中添加 __init__.py。

python -m application.app2.some_folder.some_file

这会将基目录添加到可执行文件的路径中python,然后可以通过非相对导入访问类。

解决方案 28:

如果从特定路径加载模块的目的是在开发自定义模块期间为您提供帮助,您可以在测试脚本的同一文件夹中创建指向自定义模块根目录的符号链接。对于在该文件夹中运行的任何脚本,此模块引用将优先于安装的任何其他同名模块。

我在 Linux 上测试了这个,但它应该可以在任何支持符号链接的现代操作系统上运行。

这种方法的一个优点是,您可以指向位于您自己的本地软件版本控制分支工作副本中的模块,这可以大大简化开发周期时间并减少管理不同版本模块的故障模式。

解决方案 29:

您可以使用pippip install -e .命令。您必须setup.py在项目目录的根目录中创建一个名为的文件,其中包含以下内容:

from setuptools import find_packages, setup

setup(
    name='src',
    packages=find_packages(),
    version='0.1.0',
    description='my_project',
    author='author',
    license='MIT',
)

pip install -e .之后,在项目的根目录中输入。这将使所有目录都可以以其名称作为模块进行调用。例如,如果您的根目录包含子目录module1module2,每个子目录内都有脚本,则您将能够使用以下命令从任何子目录访问它们,例如module1

import module1.script1 as script1

解决方案 30:

此问题可能是由于PyCharm

我在使用 PyCharm 时遇到了同样的问题。我的项目结构如下

skylake\n   backend\n      apps\n          example.py
      configuration\n          settings.py
   frontend\n      ...some_stuff

并且example.pyfrom configuration import settings中的代码引发了导入错误。

问题是,当我打开 PyCharm 时,它认为skylake是根路径并运行了此代码。

sys.path.extend(['D:\\projects\\skylake', 'D:/projects/skylake'])

为了解决这个问题,我刚刚将后端目录标记为源根目录。

在此处输入图片描述

它解决了我的问题。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用