我有以下文件夹结构。

application/app/folder/file.py

我想从位于另一个Python文件中的file.py导入一些功能

application/app2/some_folder/some_file.py

我试过了

from application.app.folder.file import func_name

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


#1楼

我认为,一种临时方法是按照文档中所述使用环境变量PYTHONPATHPython2Python3

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

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

#2楼

没错:

from application.app.folder.file import func_name

只要确保folder还包含__init__.py ,就可以将其作为软件包包含在内。 不知道为什么其他答案谈论PYTHONPATH


#3楼

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


#4楼

application作为您的python项目的根目录,在applicationappfolderfolder夹中创建一个空的__init__.py文件。 然后在您的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()

#5楼

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

我在Linux上进行了测试,但是它可以在任何支持符号链接的现代操作系统中使用。

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


#6楼

这对我在Windows上有效

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

import some_file

#7楼

在Linux上的python3中为我工作

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

#8楼

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

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

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

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

#9楼

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

为此,您可以更改以下内容:

from application.app.folder.file import func_name

对此:

from .application.app.folder.file import func_name

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


#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')

(注意:我认为/\\更方便,如果它不是'Windows-native'的话,因为它与Linux兼容并且更容易编写和复制到Windows资源管理器)


#11楼

默认情况下,您不能这样做。 导入文件时,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

#12楼

您可以通过按f5刷新Python Shell,或转到“运行”->“运行模块”。 这样,您无需更改目录即可从文件中读取内容。 Python将自动更改目录。 但是,如果您想使用Python Shell中不同目录中的不同文件,则可以像Cameron先前所说的那样在sys中更改目录。


#13楼

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


#14楼

就我而言,我有一个要导入的类。 我的文件如下所示:

# /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

#15楼

尝试使用Python的相对导入:

from ...app.folder.file import func_name

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


问题? 如果这对您不起作用,那么您可能会被很多陷阱的相对进口所困扰。 阅读答案和评论以获取更多详细信息: 即使使用__init__.py,也如何修复“尝试以非软件包方式进行相对导入”

提示:在每个目录级别都有__init__.py 。 您可能需要从顶级目录运行或在PYTHONPATH中具有该顶级目录的python -m application.app2.some_folder.some_file (删除.py)。


#16楼

答案不够明确,已在Python 3.6上进行了测试

使用此文件夹结构:

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

myfile.py包含以下内容:

def myfunc():
    print('hello')

main.py的import语句是:

from myfolder.myfile import myfunc
myfunc()

这将打印你好


#17楼

首次导入系统

import sys

第二追加文件夹路径

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

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

  • 名称文件
  • __初始化__.py
  • 名称模块

第四步将模块导入文件夹中

from name-folder import name-module

#18楼

因此,我只是在我的IDE上单击了鼠标右键,并添加了一个新folder并且想知道为什么我不能从其中导入。 后来我意识到我必须右键单击并创建一个Python包,而不是经典的文件系统文件夹。 或者在验尸方法中添加__init__.py (这使python将文件系统文件夹视为一个包),如其他答案所述。 以防万一有人走这条路。


#19楼

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


#20楼

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

import os, sys

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

from root_folder import file_name

#21楼

我正在研究a项目,希望用户通过pip install a以下文件列表:

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

setup.py

from setuptools import setup

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

清单

recursive-include b *.*

a / init .py

from __future__ import absolute_import

from a.a import cats
import a.b

a / a.py

cats = 0

a / b / init .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, abdogs确实等于1,正如预期的那样。


#22楼

您可以使用importlib来导入模块,在该模块中,您可以使用如下所示的字符串从文件夹中导入模块:

import importlib

scriptName = 'Snake'

script = importlib.import_module('Scripts\\.%s' % scriptName)

这个例子有一个main.py,上面的代码是一个名为Scripts的文件夹,然后您可以通过更改scriptName变量从此文件夹中调用所需的任何内容。 然后,您可以使用script来引用此模块。 例如,如果我在Snake模块中有一个名为Hello()的函数,则可以通过以下方式运行此函数:

script.Hello()

我已经在Python 3.6中测试过