from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module # Replace "my_module" here with the module name.
sys.path.pop(0)
import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')
# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft
16 回答
这是更通用的解决方案,包括sys.path中的父目录(适用于我):
关于从兄弟套餐进口的问题,我也发了类似的答案 . 你可以看到here . 以下是使用Python 3.6.5(Anaconda,conda 4.5.1),Windows 10机器进行测试的 .
没有sys.path -hacks或相对导入的解决方案
设置
我假设与问题中的文件夹结构相同
我将
.
称为根文件夹,在我的情况下,它位于C:\tmp\test_imports
中 .步骤
1)将setup.py添加到根文件夹
setup.py
的内容可以很简单基本上“任何”setup.py都可以 . 这只是一个最小的工作示例 .
2)使用虚拟环境
如果您熟悉虚拟环境,请激活一个,然后跳到下一步 . 虚拟环境的使用并非绝对必要,但从长远来看(当你有超过1个项目正在进行时)它们将真正帮助你 . 最基本的步骤是(在根文件夹中运行)
创建虚拟环境
python -m venv venv
激活虚拟环境
. /venv/bin/activate
(Linux)或./venv/Scripts/activate
(Win)要了解更多相关信息,只需谷歌“python虚拟环境教程”或类似内容 . 除了创建,激活和停用之外,您可能永远不需要任何其他命令 .
制作并激活虚拟环境后,控制台应在括号中指定虚拟环境的名称
3)将项目安装在可编辑状态
使用
pip
安装顶级包myproject
. 诀窍是在安装时使用-e
标志 . 这样,它以可编辑状态安装,对.py文件所做的所有编辑将自动包含在已安装的包中 .在根目录中,运行
pip install -e .
(注意点,它代表"current directory")您还可以看到它是使用
pip freeze
安装的4)通过将mainfolder附加到每个导入来导入
在此示例中,
mainfolder
将为ptdraft
. 这样做的好处是,您不会遇到与其他模块名称(来自python标准库或第三方模块)的名称冲突 .示例用法
nib.py
life.py
正在运行life.py
这是一个简单的答案,因此您可以看到它的工作原理,小型和跨平台 .
它只使用内置模块(
os
,sys
和inspect
)所以应该工作在任何操作系统(OS)上,因为Python就是为此而设计的 .
更短的答案代码 - 更少的行和变量
如果行数少于此数,请用
import os.path as path, sys, inspect
替换第二行,在
getsourcefile
(第3行)的开头添加inspect.
并删除第一行 .我的答案代码(更长版本)
它使用Stack Overflow回答How do I get the path of the current executed file in Python?中的示例来查找使用内置工具运行代码的源(文件名) .
我的代码为
sys.path
(python路径列表)添加了一个文件路径因为这允许Python从该文件夹导入模块 .
在代码中导入模块后,最好在新行上运行
sys.path.pop(0)
当添加的文件夹具有与导入的另一个模块同名的模块时
后来在该计划中 . 您需要删除导入前添加的列表项,而不是其他路径 .
如果您的程序没有安全删除文件路径,因为
程序结束(或重新启动Python shell)后,对
sys.path
所做的任何编辑都会消失 .关于文件名变量的注释
我的回答是不使用
__file__
变量来获取正在运行的文件路径/文件名代码,因为这里的用户经常将其描述为 unreliable . 你不应该使用它
用于从其他人使用的程序中的父文件夹导入模块 .
Some examples where it doesn't work (quote from this Stack Overflow question):
•它在某些平台上找到了can't be•有时isn't the full file path
import sys sys.path.append('../')
似乎问题与父目录中的模块或类似的东西无关 .
您需要将包含
ptdraft
的目录添加到PYTHONPATH你说
import nib
和你一起工作,这可能意味着你把ptdraft
本身(不是它的父亲)添加到了PYTHONPATH .你可以使用相对导入(python> = 2.5):
(What’s New in Python 2.5) PEP 328: Absolute and Relative Imports
EDIT :添加了另一个点'.'以上升两个包
相对导入(如
from .. import mymodule
中)仅适用于包 . 要导入当前模块的父目录中的'mymodule':edit :并不总是给出
__file__
属性 . 我现在建议使用inspect模块检索当前文件的文件名(和路径),而不是使用os.path.abspath(__file__)
如果将模块文件夹添加到PYTHONPATH不起作用,您可以修改程序中的 sys.path 列表,其中Python解释器搜索要导入的模块,python documentation说:
知道这一点,您可以在您的程序中执行以下操作:
您可以在"module search path"中使用"module search path"中的OS依赖路径 . 因此,您可以轻松添加如下所示的父目录
如果要添加父父目录,
对python 2不太了解 .
在python 3中,父文件夹可以添加如下:
...然后一个人可以从中导入模块
对我来说,访问父目录的最短和最喜欢的oneliner是:
要么:
os.getcwd()返回当前工作目录的名称,os.path.dirname(directory_name)返回传递的目录名称 .
实际上,在我看来,Python项目架构应该以子目录中没有一个模块将使用父目录中的任何模块的方式完成 . 如果发生这样的事情,重新考虑项目树是值得的 .
另一种方法是将父目录添加到PYTHONPATH系统环境变量中 .
当不在具有
__init__.py
文件的包环境中时,pathlib库(包含在> = Python 3.4中)使得将父目录的路径附加到PYTHONPATH非常简洁直观:与过去的答案相同的风格 - 但在更少的行中:P
file返回您正在使用的位置
与图书馆合作 . 创建一个名为nib的库,使用setup.py安装它,让它驻留在site-packages中,你的问题就解决了 . 您不必将所有内容都包含在一个包中 . 把它分解成碎片 .
上面提到的解决方案也很好 . 这个问题的另一个解决方案是
如果要从顶级目录导入任何内容 . 然后,
此外,如果要从父目录导入任何模块 . 然后,
此外,如果要从父目录导入任何模块 . 然后,
这样,您可以根据需要导入任何特定方法 .
在Linux系统中,您可以创建从“life”文件夹到nib.py文件的软链接 . 然后,你可以简单地导入它: