从并行文件夹导入Python
我搞不清楚怎么从一个平行的文件夹导入。
从同一个目录导入是没问题的:
project_folder
-subfolder1
-my_prog.py
-credentials.py
credentials.py 文件里包含
api_key = "supersecretapikey"
而 my_prog.py 文件里包含
import credentials
当我运行 $ python my_prog.py
时,这一切都正常。
不过,我想把 credentials 移到另一个子文件夹,像这样:
project_folder
-subfolder1
-my_prog.py
-subfolder2
-credentials.py
在这种设置下,我无法让导入工作。我尝试了一个很明显的方法,就是:
from ..subfolder2 import credentials
结果出现了一个错误
ImportError: attempted relative import with no known parent package
这个错误我不太明白。
我试着在 project_folder、subfolder1 和 subfolder2 里放 __init__.py
文件,但似乎没有什么变化。
我不想使用环境变量,因为需要在远程服务器上运行这个。
我使用的是 Python 3.12.2
2 个回答
指令 from A import B
是用来从模块 A
中导入一个组件(比如子模块、函数、变量等)B
。这和目录结构或路径没有关系,这也是你关心的问题。
Python 解释器查找要导入的模块的地方列在系统变量 sys.path
中(这是一个字符串列表)。你可以使用标准的 list.append()
方法来添加你想要导入自己模块的目录(参考 sys.path 文档):
import sys
sys.path.append('C:/Users/Sebastian/Dropbox/project_folder/subfolder2')
import credentials # reads file cedentials.py in subfolder2
注意在 Windows 上也要使用 "/",或者使用 r'c:\Users\...'
来避免 \ 被当作转义字符,或者使用 "c:\\Users\\..."
。
上面的简单例子其实是过于简化了,只是为了说明系统是如何以及在哪里搜索要导入的文件。你肯定不想使用一个固定的绝对路径。所以你应该按照以下方式来获取父文件夹 "project_folder" 的路径,然后再获取 "sister" 子文件夹的路径:
import os
myfolder = os.getcwd() # typically, "C:\\...\\project_folder\\subfolder1"
project_folder = os.path.dirname(myfolder) # should be "C:\\...\\project_folder"
sys.path.append( project_folder + "\\subfolder2" )
import credentials
另外,你可能更喜欢使用 __file__
变量,而不是 os.getcwd()
,因为 __file__
会给你当前代码所在文件的位置,而不是主程序的位置(主程序可能会把这个文件作为一个(子)模块包含进来)。
此外,你可能想把新位置插入到 sys.path
列表的开头,这样系统会先在这里查找,也可以在导入完成后将其移除。
附注:以上内容回答了“如何从平行文件夹导入”的问题。如果要获取凭证或其他数据,import
可能不是最好的选择,你应该搜索“如何读取数据文件”。
在和一个使用相对导入的文件,比如 ..otherModule
,放在同一个地方运行 Python 脚本是行不通的。你不能通过相对导入来访问父目录(或者它的子目录)里的文件,因为脚本运行的位置决定了你能访问的范围。使用相对导入时,代码会认为基础目录是你运行脚本的地方,而不是文件本身所在的位置。
解决这个问题的方法是,先进入 project_folder
文件夹,然后在那儿运行脚本(使用 "python -m subfolder1.myprog")。另外,在 my_prog.py
文件中,把 ..subfolder2
改成 subfolder2
。这样在 project_folder
中,相对导入 subfolder2
就能按你预期的方式工作了。一般来说,绝对导入会更好,因为它能消除这种混淆。