java模块路径,从相对路径导入模块

回答(23)

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

Linux用户的快捷方式

如果您只是在修补并且不关心部署问题,则可以使用符号链接(假设您的文件系统支持它)使模块或包直接在请求模块的文件夹中可见 .

ln -s (path)/module_name.py

要么

ln -s (path)/package_name

注意:"module"是任何扩展名为.py的文件,"package"是包含文件 __init__.py (可以是空文件)的任何文件夹 . 从使用的角度来看,模块和包是相同的 - 都通过 import 命令公开它们所包含的"definitions and statements" .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

对于这种情况,将Bar.py导入Foo.py,首先我将这些文件夹转换为Python包,如下所示:

dirFoo\

__init__.py

Foo.py

dirBar\

__init__.py

Bar.py

然后我会在Foo.py中这样做:

from .dirBar import Bar

如果我希望命名空间看起来像Bar.whatever,或者

from . import dirBar

如果我想要命名空间dirBar.Bar.whatever . 如果dirBar包下有更多模块,则第二种情况很有用 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

from .dirBar import Bar

代替:

from dirBar import Bar

以防万一可能安装了另一个dirBar并混淆了一个foo.py阅读器 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

没有对脚本进行任何修改的最简单方法是设置PYTHONPATH环境变量 . 因为sys.path是从这些位置初始化的:

包含输入脚本(或当前目录)的目录 .

PYTHONPATH(目录名列表,语法与shell变量PATH相同) .

依赖于安装的默认值 .

赶紧跑:

export PYTHONPATH=/absolute/path/to/your/module

您的sys.path将包含上面的路径,如下所示:

print sys.path

['', '/absolute/path/to/your/module', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

您只需使用: from Desktop.filename import something

例:

假设该文件在目录Users / user / Desktop中名为test.py,并将导入everthing .

代码:

from Desktop.test import *

但请确保在该目录中创建一个名为“ __init__.py ”的空文件

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

这也有效,并且比使用 sys 模块的任何东西都简单得多:

with open("C:/yourpath/foobar.py") as f:

eval(f.read())

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

只需简单的操作就可以从其他文件夹中导入.py文件 .

假设你有一个像这样的目录:

lib/abc.py

然后将lib文件夹中的空文件保存为named

__init__.py

然后使用

from lib.abc import

将 __init__.py 文件保留在导入模块的层次结构的每个文件夹中 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

添加 init.py 文件:

dirFoo\

Foo.py

dirBar\

__init__.py

Bar.py

然后将此代码添加到Foo.py的开头:

import sys

sys.path.append('dirBar')

import Bar

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

import os

import sys

lib_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'lib'))

sys.path.append(lib_path)

import mymodule

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

如果以这种方式构建项目:

src\

__init__.py

main.py

dirFoo\

__init__.py

Foo.py

dirBar\

__init__.py

Bar.py

然后从Foo.py你应该能够做到:

import dirFoo.Foo

要么:

from dirFoo.Foo import FooObject

根据Tom的评论,这确实要求 src 文件夹可以通过 site_packages 或您的搜索路径访问 . 此外,正如他所提到的,当您首次导入该包/目录中的模块时,会隐式导入 __init__.py . 通常 __init__.py 只是一个空文件 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

好吧,正如您所提到的,通常您希望能够访问与您的主要脚本运行位置相关的模块的文件夹,因此您只需导入它们即可 .

解:

我有 D:/Books/MyBooks.py 中的脚本和一些模块(如oldies.py) . 我需要从子目录 D:/Books/includes 导入:

import sys,site

site.addsitedir(sys.path[0] + '\\includes')

print (sys.path) # Just verify it is there

import oldies

在 oldies.py 中放置 print('done') ,以便验证一切正常 . 这种方式始终有效,因为在程序启动时初始化的Python定义 sys.path ,此列表的第一项 path[0] 是包含用于调用Python解释器的脚本的目录 .

如果脚本目录不可用(例如,如果以交互方式调用解释器或者从标准输入读取脚本), path[0] 是空字符串,它指示Python首先搜索当前目录中的模块 . 请注意,在作为 PYTHONPATH 的结果插入条目之前插入了脚本目录 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

打电话给我过于谨慎,但我喜欢让我的便携性更高,因为假设文件在每台计算机上总是在同一个地方是不安全的 . 我个人有代码首先查找文件路径 . 我使用Linux,所以我的看起来像这样:

import os, sys

from subprocess import Popen, PIPE

try:

path = Popen("find / -name 'file' -type f", shell=True, stdout=PIPE).stdout.read().splitlines()[0]

if not sys.path.__contains__(path):

sys.path.append(path)

except IndexError:

raise RuntimeError("You must have FILE to run this program!")

当然,除非您打算将这些包装在一起 . 但如果是这样的话,你真的不需要两个单独的文件 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

最简单的方法是使用sys.path.append() .

但是,您可能也对imp模块感兴趣 . 它提供对内部导入功能的访问 .

# mod_name is the filename without the .py/.pyc extention

py_mod = imp.load_source(mod_name,filename_path) # Loads .py file

py_mod = imp.load_compiled(mod_name,filename_path) # Loads .pyc file

当您不知道模块的名称时,这可用于动态加载模块 .

我过去曾经使用它来创建一个应用程序的插件类型接口,用户可以在其中编写具有特定于应用程序的函数的脚本,并且只需将脚本放在特定的目录 .

此外,这些功能可能很有用:

imp.find_module(name[, path])

imp.load_module(name, file, pathname, description)

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

另一种解决方案是安装py-require包,然后在 Foo.py 中使用以下内容

import require

Bar = require('./dirBar/Bar')

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

相对sys.path示例:

# /lib/my_module.py

# /src/test.py

if __name__ == '__main__' and __package__ is None:

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../lib')))

import my_module

基于this回答 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

我对python没有经验,所以如果我的话有任何错误,请告诉我 . 如果您的文件层次结构如下:

project\

module_1.py

module_2.py

module_1.py 定义了一个名为 func_1() 的函数, module_2.py :

from module_1 import func_1

def func_2():

func_1()

if __name__ == '__main__':

func_2()

并且您在cmd中运行 python module_2.py ,它将运行 func_1() 定义的内容 . 这通常是我们导入相同层次结构文件的方式 . 但是当你在 module_2.py 中写 from .module_1 import func_1 时,python解释器会说 No module named '__main__.module_1'; '__main__' is not a package . 因此,为了解决这个问题,我们只保留我们刚刚进行的更改,并将两个模块移动到一个包中,并将第三个模块作为调用者运行 module_2.py .

project\

package_1\

module_1.py

module_2.py

main.py

main.py :

from package_1.module_2 import func_2

def func_3():

func_2()

if __name__ == '__main__':

func_3()

但我们在 module_2.py 之前在 module_1 之前添加 . 的原因是,如果我们不这样做并运行 main.py ,python解释器会说 No module named 'module_1' ,这有点棘手, module_1.py 就在 module_2.py 旁边 . 现在我让 func_1() 在 module_1.py 做点什么:

def func_1():

print(__name__)

__name__ 记录谁调用func_1 . 现在我们在 module_1 之前保持 . ,运行 main.py ,它将打印 package_1.module_1 ,而不是 module_1 . 它表示调用 func_1() 的人与 main.py 处于同一层次结构, . 暗示 module_1 与 module_2.py 本身处于同一层次结构中 . 因此,如果没有点, main.py 将识别与自身相同的层次结构 module_1 ,它可以识别 package_1 ,但不能识别"under" .

现在让我们把它变得有点复杂 . 您有一个 config.ini ,并且模块定义了一个函数,以便在与'main.py'相同的层次结构中读取它 .

project\

package_1\

module_1.py

module_2.py

config.py

config.ini

main.py

并且由于某些不可避免的原因,您必须使用 module_2.py 调用它,因此必须从上层导入 . module_2.py :

import ..config

pass

两个点表示从上层导入(三个点访问高于上层,依此类推) . 现在我们运行 main.py ,解释器会说: ValueError:attempted relative import beyond top-level package . "top-level package"在这里是 main.py . 只是因为 config.py 在 main.py 旁边,它们处于相同的层次结构中, config.py 不是"under" main.py ,或者"leaded"不是"leaded",所以它超出 main.py . 要解决这个问题,最简单的方法是:

project\

package_1\

module_1.py

module_2.py

config.py

config.ini

main.py

我认为这与安排项目文件层次结构的原则是一致的,你应该在不同的文件夹中安排具有不同功能的模块,只需在外面留下一个顶级调用者,你就可以导入你想要的方式 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

这是相关的PEP:

特别是,假设dirFoo是dirBar的目录......

在dirFoo \ Foo.py中:

from ..dirBar import Bar

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

这是一种使用相对路径从上面的一个级别导入文件的方法 .

基本上,只需将工作目录移动到某个级别(或任何相对位置),将其添加到您的路径,然后将工作目录移回它开始的位置 .

#to import from one level above:

cwd = os.getcwd()

os.chdir("..")

below_path = os.getcwd()

sys.path.append(below_path)

os.chdir(cwd)

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

确保dirBar具有 __init__.py 文件 - 这使得目录成为Python包 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

查看标准库中的pkgutil模块 . 它可以帮助你做你想做的事 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

您还可以将子目录添加到Python路径中,以便将其作为普通脚本导入 .

import sys

sys.path.insert(0, )

import Bar

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

在我看来,最好的选择是将 __ init __.py 放在文件夹中并使用

from dirBar.Bar import *

建议不要使用sys.path.append(),因为如果使用与现有python包相同的文件名,可能会出错 . 我没有测试,但那将是模棱两可的 .

e15298c6a3b4591803e154ab0c3b3e2e.png

2 years ago

假设您的两个目录都是真正的Python包(其中包含 __init__.py 文件),这里是一个安全的解决方案,可以将模块相对于脚本的位置包含在内 .

我假设您要这样做,因为您需要在脚本中包含一组模块 . 我在几个产品的 生产环境 中使用它,并在许多特殊情况下工作,例如:从另一个目录调用的脚本或用python执行而不是打开新的解释器 .

import os, sys, inspect

# realpath() will make your script run, even if you symlink it :)

cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))

if cmd_folder not in sys.path:

sys.path.insert(0, cmd_folder)

# Use this if you want to include modules from a subfolder

cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))

if cmd_subfolder not in sys.path:

sys.path.insert(0, cmd_subfolder)

# Info:

# cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!

# __file__ fails if the script is called in different ways on Windows.

# __file__ fails if someone does os.chdir() before.

# sys.argv[0] also fails, because it doesn't not always contains the path.

作为奖励,这种方法可以让您强制Python使用您的模块而不是系统上安装的模块 .

警告!当前模块在 egg 文件中时,我真的不知道发生了什么 . 它可能也失败了 .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值