Ram*_*hum 552 python directory module path python-import
我正在运行Python 2.5.
这是我的文件夹树:
ptdraft/
nib.py
simulations/
life/
life.py
Run Code Online (Sandbox Code Playgroud)
(我也在__init__.py每个文件夹中,为了便于阅读,这里省略了)
如何nib从模块内导入life模块?我希望有可能不用修补sys.path.
注意:正在运行的主模块位于该ptdraft文件夹中.
f3l*_*lix 574
您可以使用相对导入(python> = 2.5):
from ... import nib
Run Code Online (Sandbox Code Playgroud)
(Python 2.5中的新功能)PEP 328:绝对和相对导入
编辑:添加了另一个点'.' 上两个包
Rem*_*emi 257
相对导入(如在from .. import mymodule)中仅在包中起作用.要导入当前模块的父目录中的"mymodule":
import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)
import mymodule
Run Code Online (Sandbox Code Playgroud)
编辑:__file__并不总是给出属性.而不是使用os.path.abspath(__file__)我现在建议使用inspect模块来检索当前文件的文件名(和路径)
np8*_*np8 113
关于从兄弟套餐进口的问题,我也发了类似的答案.你可以在这里看到它.以下是使用Python 3.6.5(Anaconda,conda 4.5.1),Windows 10计算机进行测试的.
我假设与问题中的文件夹结构相同
.
??? ptdraft
??? __init__.py
??? nib.py
??? simulations
??? __init__.py
??? life
??? __init__.py
??? life.py
Run Code Online (Sandbox Code Playgroud)
我调用.根文件夹,在我的情况下它位于C:\tmp\test_imports.
内容setup.py可以简单
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
Run Code Online (Sandbox Code Playgroud)
基本上"任何"setup.py都可以.这只是一个极小的工作示例.
如果您熟悉虚拟环境,请激活一个,然后跳到下一步.虚拟环境的使用并非绝对必要,但从长远来看,它们将真正帮助您(当您有超过1个项目正在进行时......).最基本的步骤是(在根文件夹中运行)
python -m venv venv. /venv/bin/activate(Linux)或./venv/Scripts/activate(Win)要了解更多相关信息,只需谷歌"python虚拟环境教程"或类似内容.除了创建,激活和停用之外,您可能永远不需要任何其他命令.
制作并激活虚拟环境后,控制台应在括号中指定虚拟环境的名称
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
Run Code Online (Sandbox Code Playgroud)
安装您的顶级包myproject使用pip.诀窍是-e在安装时使用标志.这样,它以可编辑状态安装,对.py文件所做的所有编辑将自动包含在已安装的包中.
在根目录中,运行
pip install -e . (注意点,它代表"当前目录")
您还可以看到它是使用安装的 pip freeze
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
Run Code Online (Sandbox Code Playgroud)
mainfolder到每个进口进口在这个例子中,mainfolder将是ptdraft.这样做的好处是,您不会遇到与其他模块名称(来自python标准库或第三方模块)的名称冲突.
def function_from_nib():
print('I am the return value from function_from_nib!')
Run Code Online (Sandbox Code Playgroud)
from ptdraft.nib import function_from_nib
if __name__ == '__main__':
function_from_nib()
Run Code Online (Sandbox Code Playgroud)
(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!
Run Code Online (Sandbox Code Playgroud)
has*_*sen 108
似乎问题与父目录中的模块或类似的东西无关.
您需要将包含的目录添加ptdraft到PYTHONPATH
你说这import nib与你合作,这可能意味着你把ptdraft自己(不是它的父母)添加到了PYTHONPATH.
Ric*_*llo 54
如果将模块文件夹添加到PYTHONPATH不起作用,您可以在程序中修改Python解释器搜索要导入的模块的sys.path列表,python文档说:
导入名为spam的模块时,解释器首先搜索具有该名称的内置模块.如果未找到,则会在变量sys.path给出的目录列表中搜索名为spam.py的文件.sys.path从这些位置初始化:
- 包含输入脚本(或当前目录)的目录.
- PYTHONPATH(目录名列表,语法与shell变量PATH相同).
- 依赖于安装的默认值.
初始化后,Python程序可以修改sys.path.包含正在运行的脚本的目录位于搜索路径的开头,位于标准库路径之前.这意味着将加载该目录中的脚本,而不是库目录中的同名模块.除非有意更换,否则这是一个错误.
知道了这一点,您可以在程序中执行以下操作:
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
Run Code Online (Sandbox Code Playgroud)
Shi*_*ero 45
您可以在sys.path中列出的"模块搜索路径"中使用OS依赖路径.因此,您可以轻松添加如下所示的父目录
import sys
sys.path.insert(0,'..')
Run Code Online (Sandbox Code Playgroud)
如果要添加父父目录,
sys.path.insert(0,'../..')
Run Code Online (Sandbox Code Playgroud)
小智 41
不太了解python 2.
在python 3中,父文件夹可以添加如下:
import sys
sys.path.append('..')
Run Code Online (Sandbox Code Playgroud)
...然后一个人可以从中导入模块
Edw*_*ard 29
这是一个简单的答案,因此您可以看到它的工作原理,小型和跨平台.
它仅使用内置模块(os,sys和inspect),所以应该工作
在任何操作系统(OS),因为Python是专为上.
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)
Run Code Online (Sandbox Code Playgroud)
对于比此更少的行,将第二行替换为import os.path as path, sys, inspect,在(第3行)的开头
添加并删除第一行.
- 但是这会导入所有模块,因此可能需要更多时间,内存和资源.inspect.getsourcefile
from inspect import getsourcefile
import os.path
import sys
current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]
sys.path.insert(0, parent_dir)
import my_module # Replace "my_module" here with the module name.
Run Code Online (Sandbox Code Playgroud)
它使用Stack Overflow中的示例答案如何
在Python中获取当前执行文件的路径?使用内置工具查找正在运行的代码的源(filename).
Run Code Online (Sandbox Code Playgroud)from inspect import getsourcefile from os.path import abspath接下来,无论您想从哪里找到源文件,只需使用:
Run Code Online (Sandbox Code Playgroud)abspath(getsourcefile(lambda:0))
我的代码添加了python路径列表的文件路径sys.path,
因为这允许Python从该文件夹导入模块.
在代码中导入模块后,
当添加的文件夹具有与
稍后在程序中导入的另一个模块同名的模块时,最好sys.path.pop(0)在新行上运行.您需要删除导入前添加的列表项,而不是其他路径.
如果您的程序没有导入其他模块,那么不删除文件路径是安全的,因为
在程序结束(或重新启动Python shell)之后,任何编辑都会消失.sys.path
我的答案不使用__file__变量来获取正在运行的
代码的文件路径/文件名,因为这里的用户经常将其描述为不可靠.你不应该使用它
为从父文件夹导入模块中的其他人使用的程序.
一些例子在那里不起作用(从报价这个堆栈溢出的问题):
py2exe没有__file__属性,但有一个解决方法- 从IDLE运行时
execute()没有__file__属性- OS X 10.6我得到的地方
NameError: global name '__file__' is not defined
Mik*_*ike 28
这是更通用的解决方案,包括sys.path中的父目录(适用于我):
import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
Run Code Online (Sandbox Code Playgroud)
Vin*_*san 17
两行最简单的解决方案
import os, sys
sys.path.insert(0, os.getcwd())
Run Code Online (Sandbox Code Playgroud)
如果父目录是您的工作目录并且您想从子脚本调用另一个子模块。
您可以在任何脚本中从父目录导入所有子模块并将其执行为
python child_module1/child_script.py
Run Code Online (Sandbox Code Playgroud)
Tho*_*s R 16
在 Jupyter 笔记本中
只要您在 Jupyter Notebook 中工作,这个简短的解决方案就可能有用:
%cd ..
import nib
Run Code Online (Sandbox Code Playgroud)
即使没有__init__.py文件它也能工作。
我在 Linux 和 Windows 7 上使用 Anaconda3 对其进行了测试。
小智 12
我发现以下方法可用于从脚本的父目录导入包。在示例中,我想env.py从app.db包中导入函数。
.
??? my_application
??? alembic
??? env.py
??? app
??? __init__.py
??? db
Run Code Online (Sandbox Code Playgroud)
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)
Run Code Online (Sandbox Code Playgroud)
对我来说,访问父目录的最短和最喜欢的oneliner是:
sys.path.append(os.path.dirname(os.getcwd()))
Run Code Online (Sandbox Code Playgroud)
要么:
sys.path.insert(1, os.path.dirname(os.getcwd()))
Run Code Online (Sandbox Code Playgroud)
os.getcwd()返回当前工作目录的名称,os.path.dirname(directory_name)返回传递的目录名称.
实际上,在我看来,Python项目架构应该以子目录中没有一个模块将使用父目录中的任何模块的方式完成.如果发生这样的事情,重新考虑项目树是值得的.
另一种方法是将父目录添加到PYTHONPATH系统环境变量中.
在Linux系统中,您可以创建从“life”文件夹到nib.py文件的软链接。然后,您可以简单地导入它,如下所示:
import nib
Run Code Online (Sandbox Code Playgroud)
小智 6
上述解决方案也很好。解决此问题的另一种方法是
如果要从顶层目录导入任何内容。然后,
from ...module_name import *
Run Code Online (Sandbox Code Playgroud)
另外,如果要从父目录导入任何模块。然后,
from ..module_name import *
Run Code Online (Sandbox Code Playgroud)
另外,如果要从父目录导入任何模块。然后,
from ...module_name.another_module import *
Run Code Online (Sandbox Code Playgroud)
这样,您可以根据需要导入任何特定方法。
我有一个专门针对 Git 存储库的解决方案。
首先我使用了sys.path.append('..')类似的解决方案。如果您导入的文件本身是使用sys.path.append('..').
然后我决定始终附加 Git 存储库的根目录。在一行中它看起来像这样:
sys.path.append(git.Repo('.', search_parent_directories=True).working_tree_dir)
Run Code Online (Sandbox Code Playgroud)
或者更详细地这样:
import os
import sys
import git
def get_main_git_root(path):
main_repo_root_dir = git.Repo(path, search_parent_directories=True).working_tree_dir
return main_repo_root_dir
main_repo_root_dir = get_main_git_root('.')
sys.path.append(main_repo_root_dir)
Run Code Online (Sandbox Code Playgroud)
对于最初的问题:根据存储库的根目录是什么,导入将是
import ptdraft.nib
Run Code Online (Sandbox Code Playgroud)
或者
import nib
Run Code Online (Sandbox Code Playgroud)
与过去的答案风格相同 - 但行数更少:P
import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)
Run Code Online (Sandbox Code Playgroud)
文件返回您正在工作的位置
小智 5
当不在包含__init__.py文件的包环境中时,pathlib库(包含在> = Python 3.4中)使得将父目录的路径附加到PYTHONPATH非常简洁直观:
import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))
Run Code Online (Sandbox Code Playgroud)
虽然原作者可能不再寻找解决方案,但为了完整性,有一个简单的解决方案。它将life.py作为一个模块运行,如下所示:
cd ptdraft
python -m simulations.life.life
Run Code Online (Sandbox Code Playgroud)
这样你就可以从nib.py导入任何东西,因为ptdraft目录在路径中。
| 归档时间: |
|
| 查看次数: |
590377 次 |
| 最近记录: |