导入如何在 IPython 中工作

Posted

技术标签:

【中文标题】导入如何在 IPython 中工作【英文标题】:How do imports work in IPython 【发布时间】:2014-10-06 15:21:21 【问题描述】:

我对 import 语句在 IPython 中的工作方式感到有些困惑。我通过网络搜索一无所获。

隐式相对导入适用于 Python 2,但我不知道 IPython for Python 3 是否仍然如此。

使用点语法的相对导入似乎根本不起作用:

In [6]: ls 
dsp/  __init__.py  __init__.pyc  utils/

In [7]: from .utils import capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-e7d50007bdd1> in <module>()
----> 1 from .utils import capture

ValueError: Attempted relative import in non-package

导入使用点语法的模块似乎是不可能的:

In [8]: cd utils
/home/user/workspace/mypkg/mypkg/utils

In [9]: ls
capture/  capture.py  capture.pyc  cext/  __init__.py  __init__.pyc

In [10]: from capture import Capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-10-8c31c76d052d> in <module>()
----> 1 from capture import Capture

/home/user/workspace/mypkg/mypkg/utils/capture.py in <module>()
     17 import tarfile
     18 import re
---> 19 from .. import utils
     20 from . import flprint
     21 from select import poll

ValueError: Attempted relative import in non-package

在某个地方是否有一些简明的文档?

【问题讨论】:

IPython 导入只是常规的 Python 导入,但是在包中运行它是有问题的,因为 Python 不会将工作目录视为包。 cd 上几个级别,所以你可以做from mypkg.utils.capture import Capture,它应该会正常运行。 我想我明白了。我将当前工作目录与模块在包层次结构中的位置混淆了。 是的,from . import blah 仅在您在包中时才有效。它不只是在该文件所在的目录中查找。 【参考方案1】:

问题是我从包层次结构中的较低位置导入模块,而不是模块的导入语句中使用的位置。因此,如果我 cd 进入 utils 目录并运行

from capture import Capture

然后捕获成为层次结构的顶层。所以捕获模块中的import语句

from .. import utils

超出顶层。 Python 不知道“..”指的是什么,因为模块不知道它们属于哪个包。如果我改回 mypkg 目录,我会遇到同样的问题

In [13]: cd ..
/home/user/workspace/myproj/mypkg

In [14]: from utils import capture
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-c87f26b2171d> in <module>()
----> 1 from utils import capture

/home/user/workspace/myproj/mypkg/utils/capture.py in <module>()
    18 import re
    19 import zmq
---> 20 from .. import utils
    21 from . import flprint
    22 from select import poll

ValueError: Attempted relative import beyond toplevel package

在这种情况下, utils 是顶层,所以

from . import flprint

会起作用,但是

from .. import utils

不会工作。

我必须再上移一个目录:

In [19]: cd ..
/home/user/workspace/myproj

In [20]: from mypkg.utils import capture

In [21]: cap = capture.Capture

IPython 可以导入位于当前工作目录中的包和模块,也可以从导入路径中的目录导入。我可以将包添加到导入路径,以便能够从任何工作目录导入。

In [23]: import sys

In [24]: sys.path.append('/home/user/workspace/myproj')

In [25]: cd
/home/user

In [26]: from mypkg.utils import capture

您可以使用sys.path.append 使您的模块“具有自我意识”,但正如alpha_989 所指出的,它可能会导致名称冲突。但是,在从交互式终端会话中执行包层次结构中的工作时,这是一种有用的解决方法。

【讨论】:

几个问题: 如果将sys.path添加到Python路径中,并且如果有2个同名但位于不同目录的模块,将使用首先找到的模块中的哪一个?那么你要知道所有已经使用的模块的名称,这样才不会在写程序的时候造成name-collisions @alpha_989 第一个问题:我相信这是正确的。所以在编写包模块时使用相对路径,但sys.path 在交互式会话中的包层次结构中工作时很有用。第二个问题:因为python解释器不关心你在哪里。它根据您的导入语句解释..,而不是您在文件层次结构中的位置。你告诉它 utils 是最上面的,所以任何对.. 的引用都必须比它低两级。 @alpha_989 第三个问题:包(即文件夹)会有偏好。见this post。好问题。谢谢你问他们。导入有点复杂。 感谢您指出该帖子。不是我的帖子,而是其他人向我指出了这一点。您可能会发现这篇文章很有帮助:chrisyeh96.github.io/2017/08/08/…

以上是关于导入如何在 IPython 中工作的主要内容,如果未能解决你的问题,请参考以下文章

当表在集群中的多个节点之间复制时,COPY 如何在 cassandra 中工作?

无法让导入在 web.py 项目中工作

导入时出现pycharm错误,即使它在终端中工作

如何让别名在所有 shell 中工作?

如何解决 Http 401 错误,但在邮递员中工作,而不是在 xamarin 表单中工作

%符号如何在javascript中工作[重复]