从不同的文件夹导入文件

Iva*_*van 1186 python python-import importerror

我有以下文件夹结构.

application/app/folder/file.py

我想从另一个驻留的Python文件中的file.py中导入一些函数

application/app2/some_folder/some_file.py

我试过了

from application.app.folder.file import func_name

和其他一些尝试,但到目前为止我无法正确导入.我怎样才能做到这一点?

Cam*_*ron 1253

默认情况下,你不能.导入文件时,Python只搜索当前目录,运行入口点脚本的目录,以及sys.path包括安装目录在内的位置(实际上它比这更复杂,但这涵盖了大多数情况) .

但是,您可以在运行时添加到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
Run Code Online (Sandbox Code Playgroud)

  • @pseudosudo:是的,但是,但是在开头插入它有利于保证在命名冲突的情况下在其他路径(甚至是内置路径)之前搜索路径. (356认同)
  • `sys.path.append('/ path/to/application/app/folder')`是更清洁的imo (302认同)
  • @Ofir:不,这不是一个很好的干净的pythonic解决方案.通常,您应该使用包(基于目录树).这个答案特定于所提出的问题,并且由于某种原因继续产生大量的赞成票. (41认同)
  • 它被认为是管理文件夹中的.py文件的pythonic方式吗?我想知道......为什么默认情况下不支持它?将所有.py文件保存在单个目录中没有意义.. (30认同)
  • @kreativitea - `sys.path`返回一个`list`,而不是`deque`,将`list`转换为`deque`然后返回是愚蠢的. (7认同)
  • 这很糟糕。如果我决定重构并将包移动到其他目录怎么办?我是否需要查找使用该包的所有文件并更新“sys.path.insert”语句? (3认同)
  • @Cameron“运行入口点脚本的目录”究竟是什么意思?谢谢! (2认同)
  • @ Malvin9000这意味着如果您正在处理的文件不是该程序的主文件.例如,假设您正在处理名为`foo`的模块,并且您希望它导入名为`bar`的包.现在如果你写另一个脚本,`spam`导入`foo`然后`spam`是入口点脚本,当`foo`调用`import bar` python将搜索`foo`的目录然后包含`spam`的目录. (2认同)
  • 我已经在 sys.path 中有路径。当我执行 `print(sys.path)` 时,它向我显示路径在那里,但是当我尝试导入它时,它仍然给我 **ImportError**。为什么会发生这种情况? (2认同)
  • @Cameron:然后你能提供干净的pythonic方法来做到这一点,或者提供一个解决方案的链接吗? (2认同)
  • @卡梅伦。它对我不起作用。我正在使用项目文件夹。上面有一些子文件夹。其中一个子文件夹包含一个 __init__.py 和 files.py,其中有函数。从我使用的子文件夹中的任何文件:fromfunctions_folder.functions import *,但它不起作用。 (2认同)
  • 有趣的。它只需要一个路径作为字符串。它不接受路径对象。 (2认同)

joe*_*oey 614

没有错:

from application.app.folder.file import func_name
Run Code Online (Sandbox Code Playgroud)

只需确保文件夹中还包含__init__.py,这样就可以将其作为包包含在内.不知道为什么其他答案谈论PYTHONPATH.

  • 因为这不包括需要修改"PYTHONPATH"的情况.假设你在同一级别有两个文件夹:`A`和`B`.`A`有一个`__init.py__`.尝试从`A`中的'B`导入一些东西. (42认同)
  • @Xinyang它可以是一个空文件.它的存在告诉Python将目录视为一个包. (36认同)
  • 什么是`init.py`或`__init __.py`文件? (27认同)
  • 无论我尝试什么,这都行不通.我想从"兄弟"目录导入,所以一个向上一个.所有人都有__ init __.py's,包括父母.这个python是3特定的吗? (21认同)
  • 这对me-python 3.6.1不起作用. (11认同)
  • 我正在使用 python3,它对我不起作用 (9认同)
  • 当然,这个答案假定`application`和`app`已经是包(即你已经在它们中都有`__init __.py`).将`__init __.py`也添加到`folder`的结果是,`application.app.folder`成为一个(子)*包*,你可以从中访问*module*`application.app.folder.file` ,现在可以导入其符号`func_name` (8认同)
  • 这是一个很好的答案 - 我错过了__init__.py来初始化包.还鼓励最佳实践,以减少命名空间冲突的风险.谢谢! (7认同)
  • 这不是目前最高的投票答案,但它是最正确的答案(对大多数情况而言).只需创建一个包.这并不难.需要其他答案,因为有时您可能会受限于某些系统更改(创建或修改文件等),就像测试期间一样. (7认同)
  • 即使每个文件夹中都有“__init__.py”,除非根目录位于 PYTHONPATH 中,否则相邻包的绝对导入也不起作用。我不知道怎么会有 1200 票赞成的答案,只是 [不起作用](https://i.imgur.com/4J5BKVL.png)...我假设任何人没有得到 `ModuleNotFoundError` 是通过像 PyCharm 这样的 IDE 运行他们的代码,它会自动将项目目录添加到“sys.path”。您可以在[此处](/sf/ask/5319342451/)和[此处](/sf/ask/989295261/)阅读更多信息 (6认同)
  • 在 Windows 上使用 py3.7 在命令行中运行此脚本会给我“没有名为 application.app.folder.file 的模块”。我有所有的 __init__.py ,包括父文件夹的 (5认同)
  • 为了让这个对我有用,我必须在导入模块之前添加行 `import sys` 和 `sys.path.insert(0, '')` (5认同)
  • 我有文件夹“a/test.py”和文件“b.py”作为文件夹的同一级别。即使通过将 `__init__.py` 文件添加到根文件夹(作为带有 `b.py` 的 `a` 文件夹的一侧),我也无法从 `test.py` 内的 `b.py` 文件导入函数... (3认同)
  • 这听起来像个笑话。许多人写了很多关于什么是正确的、什么是错误的事情,最后有人说这不是“没有错”...... (3认同)
  • 希望 Python 4 对这个所谓的包系统做一些明智的事情。不,无论你放置了多少个`__init__.py`,python总是找不到模块。 (3认同)
  • 这是行不通的。就那么简单。它应该有效,但事实并非如此。 (3认同)
  • `__init__.py` 语法在 https://docs.python.org/3/tutorial/modules.html#packages 中有更详细的描述,如果包驻留在系统或 PYTHONPATH (sub-)dir 或内部,则该语法很有用调用应用程序本身的目录。 (2认同)
  • 空的 __init__.py 在容器目录中至关重要,谢谢。 (2认同)
  • @borgr 我想我当时绕过了它......对不起,我不记得问题出在什么代码中,这是很久以前的事了(现在与我无关)。但似乎有一个共同的问题,所以如果其他人现在有问题,是的,请继续提出一个新问题。 (2认同)
  • 现在这个问题有解决办法吗?我找不到一种方法来规避这个问题,而且我发现将一个程序的所有文件放在一个文件夹中非常令人困惑 (2认同)
  • 考虑到隐式包命名空间,是否仍然需要“__init__.py”? (2认同)
  • 工作和不工作...当我在 IPython 控制台的“Z”级别(具有 A 和 B 作为子文件夹的文件夹)尝试“from A.file import funcA”时,工作正常。但是,在具有“from A.file import funcA”的“B”文件夹内运行“funcB”失败并引发错误(ModuleNotFoundError:没有名为“FashionColor”的模块)。请注意,运行“funcB”会将工作目录更改为“B”。所有文件夹都有 __init__.py。 (2认同)
  • ModuleNotFoundError:没有名为“应用程序”的模块:( (2认同)
  • 它不起作用 (2认同)
  • 这不起作用,太奇怪了 (2认同)
  • 我认为这不适用于 Python 3.8。我在使用这种方法时遇到了问题。 (2认同)

sli*_*izb 83

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

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py
Run Code Online (Sandbox Code Playgroud)

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

import sys
sys.path.append('../')
Run Code Online (Sandbox Code Playgroud)

  • 需要注意的是:只要导入脚本从其包含的目录运行,这就有效.否则,运行脚本的任何其他目录的父目录将附加到路径,导入将失败. (20认同)
  • 为避免这种情况,我们可以获取文件`sys.path.append(os.path.dirname(os.path.abspath(__ file __)))的父目录. (12认同)
  • @Rahul,您的解决方案不适用于交互式 shell (3认同)
  • 如果您从根文件夹(即应用程序文件夹)运行它,您可能可以使用“sys.path.append('.')”,然后使用“from app2.some_folder.some_file import your_function”导入模块。或者,对我有用的是从根文件夹运行“python3 -m app2.another_folder.another_file”。 (3认同)
  • 这对我来说不起作用 - 我必须在其中添加一个额外的目录名才能爬回父目录,以便从命令行运行 ``cli/foo.py``` 能够``import cli.bar``` (2认同)
  • 我发现这是最简单的方法。只需将相对文件路径附加到包含您需要的模块的文件中即可。就我而言: import sys sys.append('../data_struct/') 。该模块位于 data_struct/ 文件夹内的文件中 (2认同)

Ax3*_*x3l 50

我认为一种特殊的方式是使用文档中描述的环境变量PYTHONPATH:Python2,Python3

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

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
Run Code Online (Sandbox Code Playgroud)

  • 不,使用目录到.py文件的路径 (3认同)
  • 不幸的是,如果您使用的是 Anaconda,这将不起作用,因为在幕后 PYTHONPATH 并未真正在内部使用! (3认同)

Ale*_*oya 40

首先导入系统

 import sys
Run Code Online (Sandbox Code Playgroud)

第二个附加文件夹路径

sys.path.insert(0, '/the/folder/path/name-folder/')
Run Code Online (Sandbox Code Playgroud)

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

  • name-file.py
    • 名称文件夹
      • __ init __.py
      • name-module.py

四,导入文件夹内的模块

from name-folder import name-module
Run Code Online (Sandbox Code Playgroud)

  • 名称文件夹位于name-file.py的正下方,即使没有sys.path.insert命令,它也应该可以工作。这样,即使名称文件夹位于任意位置,该解决方案是否仍有效,答案就成了问题。 (4认同)

Cia*_*anB 35

您的问题是Python正在Python目录中查找此文件而未找到它.您必须指定您正在谈论您所在的目录而不是Python目录.

要做到这一点,你改变这个:

from application.app.folder.file import func_name

对此:

from .application.app.folder.file import func_name
Run Code Online (Sandbox Code Playgroud)

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

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

dan*_*y74 35

这里的答案缺乏清晰度,这是在Python 3.6上测试的

使用此文件夹结构:

main.py
|
---- myfolder/myfile.py
Run Code Online (Sandbox Code Playgroud)

myfile.py内容在哪里:

def myfunc():
    print('hello')
Run Code Online (Sandbox Code Playgroud)

import语句main.py是:

from myfolder.myfile import myfunc
myfunc()
Run Code Online (Sandbox Code Playgroud)

这将打印你好.

  • 在myfolder中添加__init__.py(空)配置文件在linux上工作(y) (8认同)
  • 可爱的图表,明确忽略了 OP 的问题。 (8认同)
  • 这与要求从文件树的不同分支导入文件而不是当前工作目录的问题完全无关. (6认同)
  • @Vincent你的意思是`__init __.py`? (5认同)
  • 这适用于Windows,但不适用于Linux (3认同)
  • 由于某些原因,添加`__init __.py`对我不起作用.我在Ubuntu 18上使用Py 3.6.5.它适用于Pycharm,但不适用于终端 (3认同)
  • 这不是OP质疑的内容。 (3认同)
  • 这根本没有回答问题。 (3认同)
  • 确实是@mrgloom (2认同)

小智 30

据我所知,__init__.py直接在要导入的函数的文件夹中添加文件即可完成工作.

  • 仅当想要包含该其他目录的脚本已在sys.path中时 (7认同)
  • 我在 Windows 上使用了 `sys.path.append(tools_dir)`,我不需要在我的目录 `tools_dir` 中添加一个 `__init__.py' 文件 (2认同)

dsg*_*g38 20

在linux上的python3中为我工作

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  
Run Code Online (Sandbox Code Playgroud)

  • `sys.path.append("/ home/linux/folder /")` - 确保不要使用快捷方式,例如``〜/ folder /"` (5认同)
  • 这是最简单的答案;也适用于 Windows。 (3认同)

Cha*_*anK 19

考虑到application作为根目录为你的Python项目,创建一个空__init__.py文件application,appfolder文件夹.然后在some_file.pymake中进行如下更改以获取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()
Run Code Online (Sandbox Code Playgroud)


Eri*_*nga 18

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

import os, sys

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

from root_folder import file_name
Run Code Online (Sandbox Code Playgroud)

  • 如果您能解释它与普通导入的不同之处,您的回答会更有帮助吗? (4认同)

wec*_*sam 16

在Python 3.4及更高版本中,您可以直接从源文件导入(链接到文档).

这是一个例子.首先,要导入的文件名为foo.py:

def announce():
    print("Imported!")
Run Code Online (Sandbox Code Playgroud)

导入上述文件的代码受到文档中示例的极大启发:

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()
Run Code Online (Sandbox Code Playgroud)

输出:

<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
Run Code Online (Sandbox Code Playgroud)

请注意,变量名称,模块名称和文件名不能匹配.此代码仍然有效:

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()
Run Code Online (Sandbox Code Playgroud)

输出:

<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
Run Code Online (Sandbox Code Playgroud)

在Python 3.1中引入了以编程方式导入模块,使您可以更好地控制模块的导入方式.有关更多信息,请参阅文档.

  • 我不知道是否有人试图理解这一点,但是我认为它太复杂了。 (8认同)
  • 这是唯一对我有用的解决方案。我在不同的目录中有相同的文件名。 (4认同)

Zec*_*umo 15

试试Python的相对导入:

from ...app.folder.file import func_name
Run Code Online (Sandbox Code Playgroud)

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


问题?如果这不适合你,那么你可能会得到许多陷阱的相对进口.阅读答案和评论以获取更多详细信息: 如何修复"非包装中尝试相对导入",即使使用__init__.py也是如此

提示:拥有__init__.py每个目录级别.您可能需要python -m application.app2.some_folder.some_file(从.py开始)从顶级目录运行或在PYTHONPATH中拥有该顶级目录.唷!

  • 如果您的目录名称以数字开头(例如不允许“import ..70_foo.test”),这似乎不起作用 (3认同)
  • 哇,这确实有效。我不知道您可以使用多个点“向上”目录。 (2认同)
  • @secluded 当然可以,但是 `import 70_foo` 也是不允许的。包和模块名称都必须是合法的标识符名称。 (2认同)

sch*_*udu 14

就我而言,我有一个要导入的类。我的文件是这样的:

# /opt/path/to/code/log_helper.py
class LogHelper:
    # stuff here
Run Code Online (Sandbox Code Playgroud)

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

import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper
Run Code Online (Sandbox Code Playgroud)

  • @not2qubit sys 未在答案中导入。 (2认同)

Eme*_*eus 13

这适用于Windows

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

import some_file
Run Code Online (Sandbox Code Playgroud)


Nag*_*gev 13

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

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

/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py
Run Code Online (Sandbox Code Playgroud)

让我们说你要导入"芒果"模块.您可以在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
Run Code Online (Sandbox Code Playgroud)

当然,您不需要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'
>>> 
Run Code Online (Sandbox Code Playgroud)

并检查os.path文档.


Moh*_*adi 13

创建包的最佳实践可以是从一个模块(如main_module.py最高级别的目录)运行和访问其他模块。

此结构演示了您可以通过使用顶级目录文件来使用和访问子包、父包或相同级别的包和模块main_module.py

创建并运行这些文件和文件夹进行测试:

 package/
    |
    |----- __init__.py (Empty file)
    |------- main_module.py (Contains: import subpackage_1.module_1)        
    |------- module_0.py (Contains: print('module_0 at parent directory, is imported'))
    |           
    |
    |------- subpackage_1/
    |           |
    |           |----- __init__.py (Empty file)
    |           |----- module_1.py (Contains: print('importing other modules from module_1...')
    |           |                             import module_0
    |           |                             import subpackage_2.module_2
    |           |                             import subpackage_1.sub_subpackage_3.module_3)
    |           |----- photo.png
    |           |
    |           |
    |           |----- sub_subpackage_3/
    |                        |
    |                        |----- __init__.py (Empty file)
    |                        |----- module_3.py (Contains: print('module_3 at sub directory, is imported')) 
    |
    |------- subpackage_2/
    |           |
    |           |----- __init__.py (Empty file)
    |           |----- module_2.py (Contains: print('module_2 at same level directory, is imported'))
Run Code Online (Sandbox Code Playgroud)

现在运行 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'
Run Code Online (Sandbox Code Playgroud)

打开图片和文件注意:

在包结构中,如果要访问照片,请使用最高级别目录中的绝对目录。

让我们假设你正在跑步main_module.py并且你想打开photo.pnginside module_1.py

什么module_1.py必须包含如下:

正确的:

image_path = 'subpackage_1/photo.png'
cv2.imread(image_path)
Run Code Online (Sandbox Code Playgroud)

错误的:

image_path = 'photo.png'
cv2.imread(image_path)
Run Code Online (Sandbox Code Playgroud)

虽然module_1.pyphoto.png都在同一个目录下。


WY *_*Hsu 11

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

Python版本:3.X

以下解决方案适用于在 Python 3.X 版中开发您的应用程序的人,因为自 Jan/1/2020 以来不支持 Python 2

项目结构

在 python 3 中,__init__.py由于隐式命名空间包,您不需要在您的项目子目录中。见的init的.py不需要在Python包3.3+

Project 
??? main.py
??? .gitignore
|
??? a
|   ??? file_a.py
|
??? b
    ??? file_b.py
Run Code Online (Sandbox Code Playgroud)

问题陈述

file_b.py,我想进口类Afile_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")
Run Code Online (Sandbox Code Playgroud)

#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")
Run Code Online (Sandbox Code Playgroud)

快乐编码!


her*_*rin 10

我很特别:我在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')
Run Code Online (Sandbox Code Playgroud)

(注意:我认为这/\事件更方便,因为它与Windows兼容,因为它与Linux兼容,并且更易于编写和复制到Windows资源管理器)

  • os.path.join('工具','mydir') (4认同)

yer*_*rty 9

以下对我有用:

\n

操作系统:Windows 10

\n

Python:v3.10.0

\n

注意:由于我是Python v3.10.0,所以我没有使用__init__.py文件,无论如何这对我不起作用。

\n
application\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 folder\n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 file.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 app2\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 some_folder\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 some_file.py\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
import sys\nsys.path.insert(1, \'C:\\\\Users\\\\<Your Username>\\\\application\')\nimport app2.some_folder.some_file\n\nsome_file.hello_world()\n
Run Code Online (Sandbox Code Playgroud)\n

替代解决方案:但是,这也对我有用:

\n
import sys\nsys.path.append( \'.\' )\nimport app2.some_folder.some_file\n\nsome_file.hello_world()\n
Run Code Online (Sandbox Code Playgroud)\n

虽然,我不明白为什么它有效。我认为点是对当前目录的引用。但是,当打印当前文件夹的路径时,当前目录已列在顶部:

\n
for path in sys.path:\n    print(path)\n
Run Code Online (Sandbox Code Playgroud)\n


小智 8

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

from <MySubFolder> import <MyFile>

MyFile 位于 MySubFolder 内。


Tim*_*inn 7

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

我在Linux上测试了它,但它应该适用于任何支持符号链接的现代操作系统.

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


小智 7

我的解决方案适用于包中包含所有必需内容__init__.py但导入仍然不起作用的人。

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

import application.app.folder.file as file
Run Code Online (Sandbox Code Playgroud)


duh*_*ime 6

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

\n\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 setup.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 MANIFEST.in\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 a\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 a.py\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 b\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 b.py\n
Run Code Online (Sandbox Code Playgroud)\n\n

安装程序.py

\n\n
from setuptools import setup\n\nsetup (\n  name='a',\n  version='0.0.1',\n  packages=['a'],\n  package_data={\n    'a': ['b/*'],\n  },\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n

清单文件

\n\n
recursive-include b *.*\n
Run Code Online (Sandbox Code Playgroud)\n\n

一个/初始化.py

\n\n
from __future__ import absolute_import\n\nfrom a.a import cats\nimport a.b\n
Run Code Online (Sandbox Code Playgroud)\n\n

a/a.py

\n\n
cats = 0\n
Run Code Online (Sandbox Code Playgroud)\n\n

a/b/初始化.py

\n\n
from __future__ import absolute_import\n\nfrom a.b.b import dogs\n
Run Code Online (Sandbox Code Playgroud)\n\n

a/b/b.py

\n\n
dogs = 1\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

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

\n\n
python setup.py install\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
import a\ndir(a)\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n


Sha*_*von 6

这对我有用。

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

python application/app2/some_folder/some_file.py
Run Code Online (Sandbox Code Playgroud)

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

python -m application.app2.some_folder.some_file
Run Code Online (Sandbox Code Playgroud)

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


Nei*_*ein 5

下面的代码以 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
Run Code Online (Sandbox Code Playgroud)

我在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())
Run Code Online (Sandbox Code Playgroud)

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


Mil*_*vić 5

????root
?   ????dir_a
?   ?   ????file_a.py
?   ?   ????file_xx.py
?   ????dir_b
?   ?   ????file_b.py
?   ?   ????file_yy.py
?   ????dir_c
?   ????dir_n
Run Code Online (Sandbox Code Playgroud)

您可以将父目录添加到PYTHONPATH,为了实现这一点,您可以使用sys.path. 因此,您可以轻松添加父目录,如下所示:

# file_b.py

import sys
sys.path.insert(0, '..')

from dir_a.file_a import func_name
Run Code Online (Sandbox Code Playgroud)


小智 5

这个问题可能是由于PyCharm

我在使用 PyCharm 时遇到了同样的问题。我有这个项目结构

skylake\
   backend\
      apps\
          example.py
      configuration\
          settings.py
   frontend\
      ...some_stuff
Run Code Online (Sandbox Code Playgroud)

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

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

sys.path.extend(['D:\\projects\\skylake', 'D:/projects/skylake'])
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

它解决了我的问题。


归档时间:

查看次数:

1208134 次

最近记录:

5 年,9 月 前