标签归档:import

导入错误:没有名为numpy的模块

问题:导入错误:没有名为numpy的模块

我有一个与此问题非常相似的问题,但仍落后了一步。我在Windows 7(对不起)64位系统上仅安装了一个Python 3版本。

我在此链接后安装了numpy- 如问题中所述。安装进行得很好,但是当我执行时

import numpy

我收到以下错误:

导入错误:没有名为numpy的模块

我知道这可能是一个超级基本的问题,但我仍在学习。

谢谢

I have a very similar question to this question, but still one step behind. I have only one version of Python 3 installed on my Windows 7 (sorry) 64-bit system.

I installed numpy following this link – as suggested in the question. The installation went fine but when I execute

import numpy

I got the following error:

Import error: No module named numpy

I know this is probably a super basic question, but I’m still learning.

Thanks


回答 0

NumPy版本1.5.0中添加了对Python 3的支持,因此,首先必须下载/安装较新版本的NumPy。

Support for Python 3 was added in NumPy version 1.5.0, so to begin with, you must download/install a newer version of NumPy.


回答 1

您可以简单地使用

pip install numpy

或者对于python3,使用

pip3 install numpy

You can simply use

pip install numpy

Or for python3, use

pip3 install numpy

回答 2

我认为numpy的安装有问题。这是我解决此问题的步骤。

  1. 请访问此网站以下载正确的软件包:http : //sourceforge.net/projects/numpy/files/
  2. 解压包装
  3. 转到文件
  4. 使用此命令安装numpy: python setup.py install

I think there are something wrong with the installation of numpy. Here are my steps to solve this problem.

  1. go to this website to download correct package: http://sourceforge.net/projects/numpy/files/
  2. unzip the package
  3. go to the document
  4. use this command to install numpy: python setup.py install

回答 3

在Windows上安装Numpy

  1. 以管理员权限打开Windows命令提示符(快速方法:按Windows键。键入“ cmd”。右键单击建议的“命令提示符”,然后选择“以管理员身份运行”)
  2. 使用“ cd”(更改目录)命令导航到Python安装目录的Scripts文件夹。例如“ cd C:\ Program Files(x86)\ PythonXX \ Scripts”

这可能是:C:\ Users \\ AppData \ Local \ Programs \ Python \ PythonXX \ ScriptsC:\ Program Files(x86)\ PythonXX \ Scripts(其中XX代表Python版本号),具体取决于安装位置。使用Windows资源管理器查找文件夹,然后将其从资源管理器地址栏中粘贴或键入地址到命令提示符中,可能会更容易。

  1. 输入以下命令:“ pip install numpy”。

下载并安装软件包后,您应该会看到类似于以下文本的内容。

Collecting numpy
  Downloading numpy-1.13.3-2-cp27-none-win32.whl (6.7MB)  
  100% |################################| 6.7MB 112kB/s
Installing collected packages: numpy
Successfully installed numpy-1.13.3

Installing Numpy on Windows

  1. Open Windows command prompt with administrator privileges (quick method: Press the Windows key. Type “cmd”. Right-click on the suggested “Command Prompt” and select “Run as Administrator)
  2. Navigate to the Python installation directory’s Scripts folder using the “cd” (change directory) command. e.g. “cd C:\Program Files (x86)\PythonXX\Scripts”

This might be: C:\Users\\AppData\Local\Programs\Python\PythonXX\Scripts or C:\Program Files (x86)\PythonXX\Scripts (where XX represents the Python version number), depending on where it was installed. It may be easier to find the folder using Windows explorer, and then paste or type the address from the Explorer address bar into the command prompt.

  1. Enter the following command: “pip install numpy”.

You should see something similar to the following text appear as the package is downloaded and installed.

Collecting numpy
  Downloading numpy-1.13.3-2-cp27-none-win32.whl (6.7MB)  
  100% |################################| 6.7MB 112kB/s
Installing collected packages: numpy
Successfully installed numpy-1.13.3

回答 4

我也遇到了这个问题(导入错误:没有名为numpy的模块),但就我而言,这是我在Mac OS X中使用PATH变量时遇到的问题。我对.bash_profile文件进行了较早的编辑,该文件导致了Anaconda安装的路径(及其他)不能正确添加。

只要在这里将此注释添加到列表中,以防其他类似我的人以相同的错误消息来到此页面并且遇到与我相同的问题。

I also had this problem (Import Error: No module named numpy) but in my case it was a problem with my PATH variables in Mac OS X. I had made an earlier edit to my .bash_profile file that caused the paths for my Anaconda installation (and others) to not be added properly.

Just adding this comment to the list here in case other people like me come to this page with the same error message and have the same problem as I had.


回答 5

您安装了适用于Python 2.6的Numpy版本-因此您只能将其与Python 2.6一起使用。您必须安装适用于Python 3.x的Numpy,例如:http : //sourceforge.net/projects/numpy/files/NumPy/1.6.1/numpy-1.6.1-win32-superpack-python3.2.exe /下载

有关不同版本的概述,请参见此处:http : //sourceforge.net/projects/numpy/files/NumPy/1.6.1/

You installed the Numpy Version for Python 2.6 – so you can only use it with Python 2.6. You have to install Numpy for Python 3.x, e.g. that one: http://sourceforge.net/projects/numpy/files/NumPy/1.6.1/numpy-1.6.1-win32-superpack-python3.2.exe/download

For an overview of the different versions, see here: http://sourceforge.net/projects/numpy/files/NumPy/1.6.1/


回答 6

安装Numpy后,我也遇到了这个问题。我通过关闭Python解释器并重新打开解决了该问题。如果其他人有此问题,可能要尝试其他方法,也许可以节省几分钟!

I had this problem too after I installed Numpy. I solved it by just closing the Python interpreter and reopening. It may be something else to try if anyone else has this problem, perhaps it will save a few minutes!


回答 7

面对同样的问题

ImportError: No module named numpy

因此,在我们的情况下(我们使用的是PIP和python 2.7),解决方案是SPLIT pip install命令:

RUN pip install numpy scipy pandas sklearn

RUN pip install numpy scipy
RUN pip install pandas sklearn

在此处找到解决方案:https : //github.com/pandas-dev/pandas/issues/25193,它是pandas的最新更新到v0.24.0

Faced with same issue

ImportError: No module named numpy

So, in our case (we are use PIP and python 2.7) the solution was SPLIT pip install commands :

From

RUN pip install numpy scipy pandas sklearn

TO

RUN pip install numpy scipy
RUN pip install pandas sklearn

Solution found here : https://github.com/pandas-dev/pandas/issues/25193, it’s related latest update of pandas to v0.24.0


回答 8

我通过pip和conda在相同的环境中安装了numpy,仅删除并重新安装其中一个是不够的。

我不得不重新安装两个。

我不知道为什么突然发生,但是解决方案是

pip uninstall numpy

conda uninstall numpy

从康达卸载也删除torchtorchvision

然后

conda install pytorch-cpu torchvision-cpu -c pytorch

pip install numpy

这为我解决了这个问题。

I had numpy installed on the same environment both by pip and by conda, and simply removing and reinstalling either was not enough.

I had to reinstall both.

I don’t know why it suddenly happened, but the solution was

pip uninstall numpy

conda uninstall numpy

uninstalling from conda also removed torch and torchvision.

then

conda install pytorch-cpu torchvision-cpu -c pytorch

and

pip install numpy

this resolved the issue for me.


回答 9

在设置用于机器学习的python时,我也面临着phyton 3的上述问题。

我遵循以下步骤:

安装python-2.7.13.msi

•设置PATH = C:\ Python27

•设置PATH = C:\ Python27 \ Scripts

前往http://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy

下载的:–numpy-1.13.1 + mkl-cp27-cp27m-win32.whl

          --scipy-0.18.0-cp27-cp27m-win32.whl 

安装numpy:pip install numpy-1.13.1 + mkl-cp27-cp27m-win32.whl

安装scipy:pip install scipy-0.18.0-cp27-cp27m-win32.whl

您可以使用以下cmds测试正确性:-

>>> import numpy
>>> import scipy
>>> import sklearn
>>> numpy.version.version
'1.13.1'
>>> scipy.version.version
'0.19.1'
>>>

I too faced the above problem with phyton 3 while setting up python for machine learning.

I followed the below steps :-

Install python-2.7.13.msi

• set PATH=C:\Python27

• set PATH=C:\Python27\Scripts

Go to http://www.lfd.uci.edu/~gohlke/pythonlibs/#scipy

Downloaded:- — numpy-1.13.1+mkl-cp27-cp27m-win32.whl

          --scipy-0.18.0-cp27-cp27m-win32.whl 

Installing numpy: pip install numpy-1.13.1+mkl-cp27-cp27m-win32.whl

Installing scipy: pip install scipy-0.18.0-cp27-cp27m-win32.whl

You can test the correctness using below cmds:-

>>> import numpy
>>> import scipy
>>> import sklearn
>>> numpy.version.version
'1.13.1'
>>> scipy.version.version
'0.19.1'
>>>

回答 10

我不确定为什么会收到错误消息,但pip3 uninstall numpy随后pip3 install numpy为我解决了该问题。

I’m not sure exactly why I was getting the error, but pip3 uninstall numpy then pip3 install numpy resolved the issue for me.


回答 11

通过Anaconda安装NumPy(使用以下命令):

  • conda安装-c conda-forge numpy
  • conda install -c conda-forge / label /破碎的numpy

For installing NumPy via Anaconda(use below commands):

  • conda install -c conda-forge numpy
  • conda install -c conda-forge/label/broken numpy

回答 12

那些正在使用的人会xonshxpip install numpy

Those who are using xonsh, do xpip install numpy.


回答 13

对于使用python 2.7的用户,应尝试:

apt-get install -y python-numpy

而不是pip install numpy

For those using python 2.7, should try:

apt-get install -y python-numpy

Instead of pip install numpy


回答 14

你可以试试:

py -3 -m pip安装anyPackageName

在您的情况下使用:

py -3 -m pip安装numpy

谢谢

You can try:

py -3 -m pip install anyPackageName

In your case use:

py -3 -m pip install numpy

Thanks


回答 15

这是numpy版本的问题,请查看$ CAFFE_ROOT / python / requirement.txt。然后执行:sudo apt-get install python-numpy> = xxx,这个问题将会解决。

this is the problem of the numpy’s version, please check out $CAFFE_ROOT/python/requirement.txt. Then exec: sudo apt-get install python-numpy>=x.x.x, this problem will be sloved.


回答 16

import numpy as np
ImportError: No module named numpy 

即使知道安装了numpy并尝试了上述所有建议都没有成功,我还是得到了这个。对我来说,解决方法是删除as np 并直接引用模块。(Centos上的python 3.4.8)。

import numpy
DataTwo=numpy.stack((OutputListUnixTwo))...
import numpy as np
ImportError: No module named numpy 

I got this even though I knew numpy was installed and unsuccessfully tried all the advice above. The fix for me was to remove the as np and directly refer to modules . (python 3.4.8 on Centos) .

import numpy
DataTwo=numpy.stack((OutputListUnixTwo))...

回答 17

您应该尝试使用以下一种安装numpy:

pip install numpy
pip2 install numpy
pip3 install numpy

由于某种原因,在我的情况下,pip2解决了该问题

You should try to install numpy using one of those:

pip install numpy
pip2 install numpy
pip3 install numpy

For some reason in my case pip2 solved the problem


回答 18

在尝试了来自各个站点的许多建议和类似问题之后,对我有用的是卸载所有Python东西并仅重新安装Anaconda(请参阅https://stackoverflow.com/a/38330088/1083292

我以前的Python安装不仅多余,而且还给我带来了麻烦。

After trying many suggestions from various sites and similar questions, what worked for me was to uninstall all Python stuff and reinstall Anaconda only (see https://stackoverflow.com/a/38330088/1083292)

The previous Python installation I had was not only redundant but only caused me trouble.


回答 19

如果在重新安装python之前工作正常,则可以解决此问题。

我只是使用以下方法解决了此问题: 如何使用自制软件在macOS中安装Python 3的早期版本?

If it was working before reinstalling python would solve the issue.

I just hit and resolved this issue using: How can I install a previous version of Python 3 in macOS using homebrew?


回答 20

对我来说,在Windows 10上,我在不知不觉中安装了多个python版本(一个来自PyCharm IDE,另一个来自Windows应用商店)。我从Windows Store卸载了一个,为了更彻底,卸载了numpy pip uninstall numpy,然后再次安装了它pip install numpy。它在PyCharm的终端和命令提示符中都可以使用。

For me, on windows 10, I had unknowingly installed multiple python versions (One from PyCharm IDE and another from Windows store). I uninstalled the one from windows Store and just to be thorough, uninstalled numpy pip uninstall numpy and then installed it again pip install numpy. It worked in the terminal in PyCharm and also in command prompt.


当模块名称中带有’-‘破折号或连字符时,如何导入模块?

问题:当模块名称中带有’-‘破折号或连字符时,如何导入模块?

我想导入foo-bar.py。这有效:

foobar = __import__("foo-bar")

这不是:

from "foo-bar" import *

我的问题:有什么办法可以使用上述格式,即from "foo-bar" import *导入其中包含的模块-

I want to import foo-bar.py. This works:

foobar = __import__("foo-bar")

This does not:

from "foo-bar" import *

My question: Is there any way that I can use the above format i.e., from "foo-bar" import * to import a module that has a - in it?


回答 0

你不能。 foo-bar不是标识符。将文件重命名为foo_bar.py

编辑:如果import不是您的目标(例如:您不在乎会发生什么sys.modules,您不需要导入自身),只需将文件的所有全局变量放入自己的作用域即可,您可以使用execfile

# contents of foo-bar.py
baz = 'quux'
>>> execfile('foo-bar.py')
>>> baz
'quux'
>>> 

you can’t. foo-bar is not an identifier. rename the file to foo_bar.py

Edit: If import is not your goal (as in: you don’t care what happens with sys.modules, you don’t need it to import itself), just getting all of the file’s globals into your own scope, you can use execfile

# contents of foo-bar.py
baz = 'quux'
>>> execfile('foo-bar.py')
>>> baz
'quux'
>>> 

回答 1

如果您不能重命名模块以匹配Python命名约定,请创建一个新模块以充当中介:

 ---- foo_proxy.py ----
 tmp = __import__('foo-bar')
 globals().update(vars(tmp))

 ---- main.py ----
 from foo_proxy import * 

If you can’t rename the module to match Python naming conventions, create a new module to act as an intermediary:

 ---- foo_proxy.py ----
 tmp = __import__('foo-bar')
 globals().update(vars(tmp))

 ---- main.py ----
 from foo_proxy import * 

回答 2

从Python 3.1开始,您可以使用importlib:

import importlib  
foobar = importlib.import_module("foo-bar")

https://docs.python.org/3/library/importlib.html

Starting from Python 3.1, you can use importlib :

import importlib  
foobar = importlib.import_module("foo-bar")

( https://docs.python.org/3/library/importlib.html )


回答 3

如果您不能重命名原始文件,则还可以使用符号链接:

ln -s foo-bar.py foo_bar.py

然后,您可以:

from foo_bar import *

If you can’t rename the original file, you could also use a symlink:

ln -s foo-bar.py foo_bar.py

Then you can just:

from foo_bar import *

回答 4

就像其他人说的那样,您不能在python命名中使用“-”,有许多解决方法,其中一种这样的解决方法在必须从路径添加多个模块的情况下非常有用。 sys.path

例如,如果您的结构是这样的:

foo-bar
├── barfoo.py
└── __init__.py
import sys
sys.path.append('foo-bar')

import barfoo

Like other said you can’t use the “-” in python naming, there are many workarounds, one such workaround which would be useful if you had to add multiple modules from a path is using sys.path

For example if your structure is like this:

foo-bar
├── barfoo.py
└── __init__.py

import sys
sys.path.append('foo-bar')

import barfoo

相对导入超出顶级包错误

问题:相对导入超出顶级包错误

似乎这里已经有很多关于python 3中相对导入的问题,但是经过许多讨论之后,我仍然找不到我问题的答案。所以这是问题。

我有一个如下所示的包裹

package/
   __init__.py
   A/
      __init__.py
      foo.py
   test_A/
      __init__.py
      test.py

我在test.py中只有一行:

from ..A import foo

现在,我在的文件夹中package,然后运行

python -m test_A.test

我收到消息

"ValueError: attempted relative import beyond top-level package"

但是如果我在的父文件夹中package,则运行:

cd ..
python -m package.test_A.test

一切安好。

现在我的问题是: 当我位于的文件夹中时packagetest_A.test根据我的理解,我在test_A子软件包中运行模块,原因是,该模块..A仅上升了一层(仍位于该package文件夹中),为什么它给出消息说beyond top-level package。究竟是什么原因导致此错误消息?

It seems there are already quite some questions here about relative import in python 3, but after going through many of them I still didn’t find the answer for my issue. so here is the question.

I have a package shown below

package/
   __init__.py
   A/
      __init__.py
      foo.py
   test_A/
      __init__.py
      test.py

and I have a single line in test.py:

from ..A import foo

now, I am in the folder of package, and I run

python -m test_A.test

I got message

"ValueError: attempted relative import beyond top-level package"

but if I am in the parent folder of package, e.g., I run:

cd ..
python -m package.test_A.test

everything is fine.

Now my question is: when I am in the folder of package, and I run the module inside the test_A sub-package as test_A.test, based on my understanding, ..A goes up only one level, which is still within the package folder, why it gives message saying beyond top-level package. What is exactly the reason that causes this error message?


回答 0

编辑:在其他问题中,这个问题有更好/更连贯的答案:


为什么不起作用?这是因为python没有记录软件包从何处加载。因此,当您这样做时python -m test_A.test,它基本上只是舍弃了test_A.test实际存储在其中的知识package(即package不被视为包)。尝试from ..A import foo正在尝试访问它没有的信息(即,已加载位置的同级目录)。从概念上讲,它类似于在中允许from ..os import path输入文件math。这将是很糟糕的,因为您希望软件包与众不同。如果他们需要使用其他软件包中的内容,则应使用全局引用它们,from os import path并让python找出与$PATHand 一起在哪里$PYTHONPATH

使用时python -m package.test_A.test,使用from ..A import foo解析就可以了,因为它可以跟踪其中的内容,package而您只是访问已加载位置的子目录。

python为什么不将当前工作目录视为软件包? 没有线索,但是天哪,它将很有用。

EDIT: There are better/more coherent answers to this question in other questions:


Why doesn’t it work? It’s because python doesn’t record where a package was loaded from. So when you do python -m test_A.test, it basically just discards the knowledge that test_A.test is actually stored in package (i.e. package is not considered a package). Attempting from ..A import foo is trying to access information it doesn’t have any more (i.e. sibling directories of a loaded location). It’s conceptually similar to allowing from ..os import path in a file in math. This would be bad because you want the packages to be distinct. If they need to use something from another package, then they should refer to them globally with from os import path and let python work out where that is with $PATH and $PYTHONPATH.

When you use python -m package.test_A.test, then using from ..A import foo resolves just fine because it kept track of what’s in package and you’re just accessing a child directory of a loaded location.

Why doesn’t python consider the current working directory to be a package? NO CLUE, but gosh it would be useful.


回答 1

import sys
sys.path.append("..") # Adds higher directory to python modules path.

尝试这个。为我工作。

import sys
sys.path.append("..") # Adds higher directory to python modules path.

Try this. Worked for me.


回答 2

假设:
如果您在package目录中,A并且test_A是单独的软件包。

结论:
..A只允许在包装内进口。

进一步说明:
如果要强制将软件包放置在上的任何路径上,则使相对导入仅在软件包内可用是很有用的sys.path

编辑:

我是唯一认为这很疯狂的人吗?为什么在世界上当前的工作目录不被视为软件包?–多猎人

当前的工作目录通常位于sys.path中。因此,所有文件都可以导入。这是自Python 2以来尚不存在的软件包的行为。将运行目录打包,可以将模块导入为“ import .A”和“ import A”,这将是两个不同的模块。也许这是一个不一致的考虑。

Assumption:
If you are in the package directory, A and test_A are separate packages.

Conclusion:
..A imports are only allowed within a package.

Further notes:
Making the relative imports only available within packages is useful if you want to force that packages can be placed on any path located on sys.path.

EDIT:

Am I the only one who thinks that this is insane!? Why in the world is the current working directory not considered to be a package? – Multihunter

The current working directory is usually located in sys.path. So, all files there are importable. This is behavior since Python 2 when packages did not yet exist. Making the running directory a package would allow imports of modules as “import .A” and as “import A” which then would be two different modules. Maybe this is an inconsistency to consider.


回答 3

在3.6中,这些解决方案都不适用于我,其文件夹结构如下:

package1/
    subpackage1/
        module1.py
package2/
    subpackage2/
        module2.py

我的目标是从module1导入module2。最终对我有用的是:

import sys
sys.path.append(".")

请注意,单点与到目前为止提到的两点解决方案不同。


编辑:以下帮助为我澄清了这一点:

import os
print (os.getcwd())

就我而言,工作目录是(意外地)项目的根目录。

None of these solutions worked for me in 3.6, with a folder structure like:

package1/
    subpackage1/
        module1.py
package2/
    subpackage2/
        module2.py

My goal was to import from module1 into module2. What finally worked for me was, oddly enough:

import sys
sys.path.append(".")

Note the single dot as opposed to the two-dot solutions mentioned so far.


Edit: The following helped clarify this for me:

import os
print (os.getcwd())

In my case, the working directory was (unexpectedly) the root of the project.


回答 4

from package.A import foo

我认为这比

import sys
sys.path.append("..")

from package.A import foo

I think it’s clearer than

import sys
sys.path.append("..")

回答 5

正如最流行的答案所暗示的,基本上是因为您的PYTHONPATHsys.path包括.但不包括您通往包裹的路径。相对导入相对于您当前的工作目录,而不是相对于导入发生的文件;奇怪。

您可以通过以下方法解决此问题:首先将相对导入更改为绝对导入,然后以以下内容开头:

PYTHONPATH=/path/to/package python -m test_A.test

或以这种方式强制执行python路径,因为:

随着python -m test_A.test你在执行test_A/test.py__name__ == '__main__'__file__ == '/absolute/path/to/test_A/test.py'

这意味着test.py您可以import在主要情况下使用绝对半保护,并且还可以执行一些一次性的Python路径操作:

from os import path

def main():

if __name__ == '__main__':
    import sys
    sys.path.append(path.join(path.dirname(__file__), '..'))
    from A import foo

    exit(main())

As the most popular answer suggests, basically its because your PYTHONPATH or sys.path includes . but not your path to your package. And the relative import is relative to your current working directory, not the file where the import happens; oddly.

You could fix this by first changing your relative import to absolute and then either starting it with:

PYTHONPATH=/path/to/package python -m test_A.test

OR forcing the python path when called this way, because:

With python -m test_A.test you’re executing test_A/test.py with __name__ == '__main__' and __file__ == '/absolute/path/to/test_A/test.py'

That means that in test.py you could use your absolute import semi-protected in the main case condition and also do some one-time Python path manipulation:

from os import path
…
def main():
…
if __name__ == '__main__':
    import sys
    sys.path.append(path.join(path.dirname(__file__), '..'))
    from A import foo

    exit(main())

回答 6

编辑:2020-05-08:看来我引用的网站不再受撰写建议的人控制,因此我正在删除指向该网站的链接。感谢您让我知道baxx。


如果在提供了很好的答案后仍然有人在挣扎,我在网站上找不到了建议。

我提到的网站的基本报价:

“可以通过这种方式以编程方式指定相同的内容:

导入系统

sys.path.append(’..’)

当然,以上代码必须在其他import 语句之前编写

很明显,必须这样,事后才思考。我试图在测试中使用sys.path.append(’..’),但遇到了OP发布的问题。通过在其他导入之前添加import和sys.path定义,我可以解决此问题。

Edit: 2020-05-08: Is seems the website I quoted is no longer controlled by the person who wrote the advice, so I’m removing the link to the site. Thanks for letting me know baxx.


If someone’s still struggling a bit after the great answers already provided, I found advice on a website that no longer is available.

Essential quote from the site I mentioned:

“The same can be specified programmatically in this way:

import sys

sys.path.append(‘..’)

Of course the code above must be written before the other import statement.

It’s pretty obvious that it has to be this way, thinking on it after the fact. I was trying to use the sys.path.append(‘..’) in my tests, but ran into the issue posted by OP. By adding the import and sys.path defintion before my other imports, I was able to solve the problem.


回答 7

如果__init__.py在上层文件夹中有一个,则可以像import file/path as alias在该init文件中一样初始化导入 。然后,您可以在较低的脚本上使用它,如下所示:

import alias

if you have an __init__.py in an upper folder, you can initialize the import as import file/path as alias in that init file. Then you can use it on lower scripts as:

import alias

回答 8

以我的拙见,我以这种方式理解这个问题:

[案例1]当您开始像

python -m test_A.test

要么

import test_A.test

要么

from test_A import test

您实际上是将import-anchor设置为test_A,换句话说,顶级包是test_A。因此,当我们拥有test.py do时from ..A import xxx,您就逃脱了锚点,Python不允许这样做。

[情况2]

python -m package.test_A.test

要么

from package.test_A import test

您的锚变为package,因此package/test_A/test.py这样from ..A import xxx做不会逃脱锚(仍位于package文件夹中),Python会很乐意接受这一点。

简而言之:

  • 绝对导入更改当前锚点(=重新定义顶级程序包);
  • 相对导入不会更改锚,但会限制在锚内。

此外,我们可以使用标准模块名称(FQMN)来检查此问题。

分别检查FQMN:

  • [CASE2] test.__name__=package.test_A.test
  • [CASE1] test.__name__=test_A.test

因此,对于CASE2,from .. import xxx将产生一个FQMN =的新模块package.xxx,这是可以接受的。

对于CASE1,..from from .. import xxx将从中跳出的起始节点(锚点)test_A,而Python不允许这样做。

In my humble opinion, I understand this question in this way:

[CASE 1] When you start an absolute-import like

python -m test_A.test

or

import test_A.test

or

from test_A import test

you’re actually setting the import-anchor to be test_A, in other word, top-level package is test_A . So, when we have test.py do from ..A import xxx, you are escaping from the anchor, and Python does not allow this.

[CASE 2] When you do

python -m package.test_A.test

or

from package.test_A import test

your anchor becomes package, so package/test_A/test.py doing from ..A import xxx does not escape the anchor(still inside package folder), and Python happily accepts this.

In short:

  • Absolute-import changes current anchor (=redefines what is the top-level package);
  • Relative-import does not change the anchor but confines to it.

Furthermore, we can use full-qualified module name(FQMN) to inspect this problem.

Check FQMN in each case:

  • [CASE2] test.__name__ = package.test_A.test
  • [CASE1] test.__name__ = test_A.test

So, for CASE2, an from .. import xxx will result in a new module with FQMN=package.xxx, which is acceptable.

While for CASE1, the .. from within from .. import xxx will jump out of the starting node(anchor) of test_A, and this is NOT allowed by Python.


回答 9

不确定在python 2.x中,但在python 3.6中,假设您尝试运行整个套件,则只需使用 -t

-t,–top-level-directory directory项目的顶级目录(默认为开始目录)

所以,在像

project_root
  |
  |----- my_module
  |          \
  |           \_____ my_class.py
  |
  \ tests
      \___ test_my_func.py

例如,可以使用:

python3 unittest discover -s /full_path/project_root/tests -t /full_path/project_root/

并且仍然导入my_module.my_class没有重大戏剧的地方。

Not sure in python 2.x but in python 3.6, assuming you are trying to run the whole suite, you just have to use -t

-t, –top-level-directory directory Top level directory of project (defaults to start directory)

So, on a structure like

project_root
  |
  |----- my_module
  |          \
  |           \_____ my_class.py
  |
  \ tests
      \___ test_my_func.py

One could for example use:

python3 unittest discover -s /full_path/project_root/tests -t /full_path/project_root/

And still import the my_module.my_class without major dramas.


从Python中的另一个文件调用函数

问题:从Python中的另一个文件调用函数

设置:我需要在程序中使用每个函数的.py文件。

在此程序中,我需要从外部文件调用该函数。

我试过了:

from file.py import function(a,b)

但是我得到了错误:

ImportError:没有名为“ file.py”的模块;文件不是包

我该如何解决这个问题?

Set_up: I have a .py file for each function I need to use in a program.

In this program, I need to call the function from the external files.

I’ve tried:

from file.py import function(a,b)

But I get the error:

ImportError: No module named ‘file.py’; file is not a package

How do I fix this problem?


回答 0

file.py导入时无需添加任何内容。只需编写from file import function,然后使用调用函数function(a, b)。之所以可能不起作用,是因为它file是Python的核心模块之一,所以我建议您更改文件名。

请注意,如果您尝试将函数从导入a.py到名为的文件中b.py,则需要确保a.pyb.py处于同一目录中。

There isn’t any need to add file.py while importing. Just write from file import function, and then call the function using function(a, b). The reason why this may not work, is because file is one of Python’s core modules, so I suggest you change the name of your file.

Note that if you’re trying to import functions from a.py to a file called b.py, you will need to make sure that a.py and b.py are in the same directory.


回答 1

首先,您不需要.py

如果您有文件a.py并且内部有一些功能:

def b():
  # Something
  return 1

def c():
  # Something
  return 2

而您要导入它们,z.py您必须编写

from a import b, c

First of all you do not need a .py.

If you have a file a.py and inside you have some functions:

def b():
  # Something
  return 1

def c():
  # Something
  return 2

And you want to import them in z.py you have to write

from a import b, c

回答 2

您可以通过2种方式执行此操作。首先只是从file.py导入所需的特定功能。为此使用

from file import function

另一种方法是导入整个文件

import file as fl

然后您可以使用以下命令在file.py中调用任何函数

fl.function(a,b)

You can do this in 2 ways. First is just to import the specific function you want from file.py. To do this use

from file import function

Another way is to import the entire file

import file as fl

Then you can call any function inside file.py using

fl.function(a,b)

回答 3

如果您不能或不想在正在使用的同一目录中使用该函数,也可以从其他目录中调用该函数。您可以通过两种方式来做到这一点(也许还有更多选择,但这是对我有用的选择)。

备选方案1临时更改您的工作目录

import os

os.chdir("**Put here the directory where you have the file with your function**")

from file import function

os.chdir("**Put here the directory where you were working**")

选择2将具有功能的目录添加到sys.path

import sys

sys.path.append("**Put here the directory where you have the file with your function**")

from file import function

You can call the function from a different directory as well, in case you cannot or do not want to have the function in the same directory you are working. You can do this in two ways (perhaps there are more alternatives, but these are the ones that have worked for me).

Alternative 1 Temporarily change your working directory

import os

os.chdir("**Put here the directory where you have the file with your function**")

from file import function

os.chdir("**Put here the directory where you were working**")

Alternative 2 Add the directory where you have your function to sys.path

import sys

sys.path.append("**Put here the directory where you have the file with your function**")

from file import function

回答 4

如果您的文件位于不同的包结构中,并且您想从其他包中调用它,则可以按照以下方式调用它:

假设您在python项目中具有以下包结构:

com.my.func.DifferentFunction-python文件中,您具有一些功能,例如:

def add(arg1, arg2):
    return arg1 + arg2

def sub(arg1, arg2) :
    return arg1 - arg2

def mul(arg1, arg2) :
    return arg1 * arg2

您想从中调用不同的函数Example3.py,然后按照以下方式进行操作:

Example3.py文件中定义导入语句以导入所有功能

from com.my.func.DifferentFunction import *

或定义要导入的每个函数名称

from com.my.func.DifferentFunction import add, sub, mul

然后Example3.py可以调用函数执行:

num1 = 20
num2 = 10

print("\n add : ", add(num1,num2))
print("\n sub : ", sub(num1,num2))
print("\n mul : ", mul(num1,num2))

输出:

 add :  30

 sub :  10

 mul :  200

If your file is in the different package structure and you want to call it from a different package, then you can call it in that fashion:

Let’s say you have following package structure in your python project:

in – com.my.func.DifferentFunction python file you have some function, like:

def add(arg1, arg2):
    return arg1 + arg2

def sub(arg1, arg2) :
    return arg1 - arg2

def mul(arg1, arg2) :
    return arg1 * arg2

And you want to call different functions from Example3.py, then following way you can do it:

Define import statement in Example3.py – file for import all function

from com.my.func.DifferentFunction import *

or define each function name which you want to import

from com.my.func.DifferentFunction import add, sub, mul

Then in Example3.py you can call function for execute:

num1 = 20
num2 = 10

print("\n add : ", add(num1,num2))
print("\n sub : ", sub(num1,num2))
print("\n mul : ", mul(num1,num2))

Output:

 add :  30

 sub :  10

 mul :  200

回答 5

遇到了相同的功能,但我必须执行以下操作才能使其正常工作。

如果看到“ ModuleNotFoundError:未命名模块”,则可能需要在文件名前面加点号(。),如下所示;

.file导入功能

Came across the same feature but I had to do the below to make it work.

If you are seeing ‘ModuleNotFoundError: No module named’, you probably need the dot(.) in front of the filename as below;

from .file import funtion


回答 6

首先以.py格式保存文件(例如my_example.py)。如果该文件具有功能,

def xyz():

        --------

        --------

def abc():

        --------

        --------

在调用函数中,您只需要键入以下几行。

文件名:my_example2.py

===========================

import my_example.py


a = my_example.xyz()

b = my_example.abc()

===========================

First save the file in .py format (for example, my_example.py). And if that file have functions,

def xyz():

        --------

        --------

def abc():

        --------

        --------

In the calling function you just have to type the below lines.

file_name: my_example2.py

============================

import my_example.py


a = my_example.xyz()

b = my_example.abc()

============================


回答 7

将模块重命名为“文件”以外的名称。

然后还要确保在调用函数时:

1)如果要导入整个模块,则在调用它时要重申模块名称:

import module
module.function_name()

要么

import pizza
pizza.pizza_function()

2)或如果您要导入特定功能,带别名的功能或所有使用*的功能,则无需重复模块名称:

from pizza import pizza_function
pizza_function()

要么

from pizza import pizza_function as pf
pf()

要么

from pizza import *
pizza_function()

Rename the module to something other than ‘file’.

Then also be sure when you are calling the function that:

1)if you are importing the entire module, you reiterate the module name when calling it:

import module
module.function_name()

or

import pizza
pizza.pizza_function()

2)or if you are importing specific functions, functions with an alias, or all functions using *, you don’t reiterate the module name:

from pizza import pizza_function
pizza_function()

or

from pizza import pizza_function as pf
pf()

or

from pizza import *
pizza_function()

回答 8

.py文件中的函数(可以(当然)可以在不同目录中)可以通过首先写入目录然后输入不带.py扩展名的文件名来简单地导入:

from directory_name.file_name import function_name

后来被使用: function_name()

Functions from .py file (can (of course) be in different directory) can be simply imported by writing directories first and then the file name without .py extension:

from directory_name.file_name import function_name

And later be used: function_name()


回答 9

在MathMethod.Py内部。

def Add(a,b):
   return a+b 

def subtract(a,b):
  return a-b

内部Main.Py

import MathMethod as MM 
  print(MM.Add(200,1000))

输出:1200

Inside MathMethod.Py.

def Add(a,b):
   return a+b 

def subtract(a,b):
  return a-b

Inside Main.Py

import MathMethod as MM 
  print(MM.Add(200,1000))

Output:1200


回答 10

您不必添加file.py

只需将文件与文件导入位置保持在相同位置即可。然后只需导入您的函数:

from file import a, b

You don’t have to add file.py.

Just keep the file in the same location with the file from where you want to import it. Then just import your functions:

from file import a, b

回答 11

您应该将文件与要导入的Python文件放在同一位置。“从文件导入功能”也足够。

You should have the file at the same location as that of the Python files you are trying to import. Also ‘from file import function’ is enough.


回答 12

如果要导入此文件,请在文件名前附加一个点(。),该文件与运行代码的目录相同。

例如,我正在运行一个名为a.py的文件,我想导入一个名为addFun的方法,该方法是用b.py编写的,而b.py在同一目录中

从.b import addFun

append a dot(.) in front of a file name if you want to import this file which is in the same directory where you are running your code.

For example, i’m running a file named a.py and i want to import a method named addFun which is written in b.py, and b.py is there in the same directory

from .b import addFun


回答 13

假设您要调用的文件是anotherfile.py,并且您要调用的方法是method1,然后先导入文件,然后再导入方法

from anotherfile import method1

如果method1是类的一部分,则将该类设为class1,则

from anotherfile import class1

然后创建一个class1对象,假设对象名称是ob1,然后

ob1 = class1()
ob1.method1()

Suppose the file you want to call is anotherfile.py and the method you want to call is method1, then first import the file and then the method

from anotherfile import method1

if method1 is part of a class, let the class be class1, then

from anotherfile import class1

then create an object of class1, suppose the object name is ob1, then

ob1 = class1()
ob1.method1()

回答 14

就我而言,我命名了文件helper.scrap.py,直到更改为helper.py

in my case i named my file helper.scrap.py and couldn’t make it work until i changed to helper.py


相对进口量为十亿次

问题:相对进口量为十亿次

我来过这里:

以及很多我没有复制的URL,有些在SO上,有些在其他网站上,当我以为我很快就会找到解决方案时。

永远存在的问题是:在Windows 7、32位Python 2.7.3中,如何解决此“尝试以非软件包方式进行相对导入”消息?我在pep-0328上构建了该软件包的精确副本:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py

导入是从控制台完成的。

我确实在相应的模块中创建了名为垃圾邮件和鸡蛋的函数。自然,它不起作用。答案显然是在我列出的第4个网址中,但对我来说都是校友。我访问的其中一个URL上有此响应:

相对导入使用模块的名称属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,将其设置为“ main”),则相对导入的解析就好像该模块是顶级模块一样,无论该模块实际位于文件系统上的哪个位置。

上面的回答看起来很有希望,但对我来说,全都是象形文字。所以我的问题是,如何使Python不返回“未包装的相对导入尝试”?可能有一个涉及-m的答案。

有人可以告诉我为什么Python会给出该错误消息,“非包装”的含义,为什么以及如何定义“包装”以及准确的答案,这些措辞足以使幼儿园的学生理解

I’ve been here:

and plenty of URLs that I did not copy, some on SO, some on other sites, back when I thought I’d have the solution quickly.

The forever-recurring question is this: With Windows 7, 32-bit Python 2.7.3, how do I solve this “Attempted relative import in non-package” message? I built an exact replica of the package on pep-0328:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py

The imports were done from the console.

I did make functions named spam and eggs in their appropriate modules. Naturally, it didn’t work. The answer is apparently in the 4th URL I listed, but it’s all alumni to me. There was this response on one of the URLs I visited:

Relative imports use a module’s name attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to ‘main’) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

The above response looks promising, but it’s all hieroglyphs to me. So my question, how do I make Python not return to me “Attempted relative import in non-package”? has an answer that involves -m, supposedly.

Can somebody please tell me why Python gives that error message, what it means by “non-package”, why and how do you define a ‘package’, and the precise answer put in terms easy enough for a kindergartener to understand.


回答 0

脚本与模块

这是一个解释。简短的版本是直接运行Python文件与从其他位置导入该文件之间存在很大差异。 仅知道文件位于哪个目录并不能确定Python认为位于哪个软件包。 此外,这还取决于您如何通过运行或导入将文件加载到Python中。

加载Python文件的方式有两种:作为顶级脚本或作为模块。如果直接执行文件(例如,python myfile.py在命令行上键入),则将文件作为顶级脚本加载。如果您这样做python -m myfile,则将其作为模块加载,或者import在其他文件中遇到语句时将其加载。一次只能有一个顶级脚本。顶层脚本是您为了开始而运行的Python文件。

命名

加载文件时,将为其指定一个名称(存储在其__name__属性中)。如果已将其作为顶级脚本加载,则其名称为__main__。如果将其作为模块加载,则其名称为文件名,其后是其所属的所有软件包/子软件包的名称,并用点号分隔。

例如,在您的示例中:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
    moduleA.py

如果您导入moduleX(请注意:imported,不直接执行),则其名称为package.subpackage1.moduleX。如果导入moduleA,则名称为package.moduleA。但是,如果直接从命令行运行 moduleX,则名称为__main__,如果直接从命令行运行moduleA,则名称为__main__。当模块作为顶级脚本运行时,它将失去其常规名称,而其名称改为__main__

不通过其包含的包访问模块

还有一个额外的问题:模块的名称取决于它是从其所在目录“直接”导入还是通过软件包导入。仅当您在目录中运行Python并尝试将文件导入同一目录(或其子目录)时,这才有所不同。例如,如果您在目录中启动Python解释器package/subpackage1,然后执行do import moduleX,则其名称moduleX将仅为moduleX,而不是package.subpackage1.moduleX。这是因为Python在启动时会将当前目录添加到其搜索路径中。如果它在当前目录中找到了要导入的模块,则不会知道该目录是软件包的一部分,并且软件包信息也不会成为模块名称的一部分。

一种特殊情况是,如果您以交互方式运行解释器(例如,只需键入python并开始即时输入Python代码)。在这种情况下,该交互式会话的名称为__main__

现在,这是您的错误消息的关键所在:如果模块的名称没有点,则不认为它是包的一部分。文件实际在磁盘上的哪个位置都没有关系。重要的是它的名称是什么,它的名称取决于您如何加载它。

现在查看您在问题中包含的报价:

相对导入使用模块的名称属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,将其设置为“ main”),则相对导入的解析就好像该模块是顶级模块一样,无论该模块实际位于文件系统上的哪个位置。

相对进口…

相对导入使用模块的名称来确定模块在包中的位置。当您使用类似的相对导入时from .. import foo,点表示在包层次结构中增加了一些级别。例如,如果您当前模块的名称为package.subpackage1.moduleX,则..moduleA表示package.moduleA。为了使a from .. import起作用,模块的名称必须至少包含与import语句中一样多的点。

…只是相对的

但是,如果模块的名称为__main__,则不认为它在软件包中。它的名称没有点,因此您不能from .. import在其中使用语句。如果您尝试这样做,则会收到“非包中的相对导入”错误。

脚本无法导入相对

您可能所做的是尝试从命令行运行moduleX等。执行此操作时,其名称设置为__main__,这意味着其中的相对导入将失败,因为它的名称不会显示它在软件包中。请注意,如果您从模块所在的同一目录运行Python,然后尝试导入该模块,也会发生这种情况,因为如上所述,Python会“过早”在当前目录中找到该模块,而没有意识到它是包装的一部分。

还请记住,当您运行交互式解释器时,该交互式会话的“名称”始终为__main__。因此,您不能直接从交互式会话进行相对导入。相对导入仅在模块文件中使用。

两种解决方案:

  1. 如果您确实确实想moduleX直接运行,但是仍然希望将其视为软件包的一部分,则可以这样做python -m package.subpackage1.moduleX。该命令-m告诉Python将其作为模块而不是顶级脚本进行加载。

  2. 或者,也许您实际上并不想运行 moduleX,而只想运行其他脚本,例如myfile.py,该脚本使用 inside函数moduleX。如果是这样的话,把myfile.py 其他地方没有内部package目录-并运行它。如果myfile.py您在内部执行类似的操作from package.moduleA import spam,则效果很好。

笔记

  • 对于这两种解决方案,都package必须可以从Python模块搜索路径(sys.path)访问包目录(在您的示例中)。如果不是,您将根本无法可靠地使用包装中的任何物品。

  • 从Python 2.6开始,用于程序包解析的模块的“名称”不仅由其__name__属性确定,而且由__package__属性确定。这就是为什么我避免使用显式符号__name__来引用模块的“名称”的原因。因为Python 2.6模块的“名”是有效的__package__ + '.' + __name__,或者只是__name__如果__package__None)。

Script vs. Module

Here’s an explanation. The short version is that there is a big difference between directly running a Python file, and importing that file from somewhere else. Just knowing what directory a file is in does not determine what package Python thinks it is in. That depends, additionally, on how you load the file into Python (by running or by importing).

There are two ways to load a Python file: as the top-level script, or as a module. A file is loaded as the top-level script if you execute it directly, for instance by typing python myfile.py on the command line. It is loaded as a module if you do python -m myfile, or if it is loaded when an import statement is encountered inside some other file. There can only be one top-level script at a time; the top-level script is the Python file you ran to start things off.

Naming

When a file is loaded, it is given a name (which is stored in its __name__ attribute). If it was loaded as the top-level script, its name is __main__. If it was loaded as a module, its name is the filename, preceded by the names of any packages/subpackages of which it is a part, separated by dots.

So for instance in your example:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
    moduleA.py

if you imported moduleX (note: imported, not directly executed), its name would be package.subpackage1.moduleX. If you imported moduleA, its name would be package.moduleA. However, if you directly run moduleX from the command line, its name will instead be __main__, and if you directly run moduleA from the command line, its name will be __main__. When a module is run as the top-level script, it loses its normal name and its name is instead __main__.

Accessing a module NOT through its containing package

There is an additional wrinkle: the module’s name depends on whether it was imported “directly” from the directory it is in, or imported via a package. This only makes a difference if you run Python in a directory, and try to import a file in that same directory (or a subdirectory of it). For instance, if you start the Python interpreter in the directory package/subpackage1 and then do import moduleX, the name of moduleX will just be moduleX, and not package.subpackage1.moduleX. This is because Python adds the current directory to its search path on startup; if it finds the to-be-imported module in the current directory, it will not know that that directory is part of a package, and the package information will not become part of the module’s name.

A special case is if you run the interpreter interactively (e.g., just type python and start entering Python code on the fly). In this case the name of that interactive session is __main__.

Now here is the crucial thing for your error message: if a module’s name has no dots, it is not considered to be part of a package. It doesn’t matter where the file actually is on disk. All that matters is what its name is, and its name depends on how you loaded it.

Now look at the quote you included in your question:

Relative imports use a module’s name attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to ‘main’) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

Relative imports…

Relative imports use the module’s name to determine where it is in a package. When you use a relative import like from .. import foo, the dots indicate to step up some number of levels in the package hierarchy. For instance, if your current module’s name is package.subpackage1.moduleX, then ..moduleA would mean package.moduleA. For a from .. import to work, the module’s name must have at least as many dots as there are in the import statement.

… are only relative in a package

However, if your module’s name is __main__, it is not considered to be in a package. Its name has no dots, and therefore you cannot use from .. import statements inside it. If you try to do so, you will get the “relative-import in non-package” error.

Scripts can’t import relative

What you probably did is you tried to run moduleX or the like from the command line. When you did this, its name was set to __main__, which means that relative imports within it will fail, because its name does not reveal that it is in a package. Note that this will also happen if you run Python from the same directory where a module is, and then try to import that module, because, as described above, Python will find the module in the current directory “too early” without realizing it is part of a package.

Also remember that when you run the interactive interpreter, the “name” of that interactive session is always __main__. Thus you cannot do relative imports directly from an interactive session. Relative imports are only for use within module files.

Two solutions:

  1. If you really do want to run moduleX directly, but you still want it to be considered part of a package, you can do python -m package.subpackage1.moduleX. The -m tells Python to load it as a module, not as the top-level script.

  2. Or perhaps you don’t actually want to run moduleX, you just want to run some other script, say myfile.py, that uses functions inside moduleX. If that is the case, put myfile.py somewhere elsenot inside the package directory – and run it. If inside myfile.py you do things like from package.moduleA import spam, it will work fine.

Notes

  • For either of these solutions, the package directory (package in your example) must be accessible from the Python module search path (sys.path). If it is not, you will not be able to use anything in the package reliably at all.

  • Since Python 2.6, the module’s “name” for package-resolution purposes is determined not just by its __name__ attributes but also by the __package__ attribute. That’s why I’m avoiding using the explicit symbol __name__ to refer to the module’s “name”. Since Python 2.6 a module’s “name” is effectively __package__ + '.' + __name__, or just __name__ if __package__ is None.)


回答 1

这确实是python中的问题。混淆的根源是人们错误地将相对进口作为相对的进口,而不是。

例如,当您在faa.py中编写时:

from .. import foo

这具有只有一个意思faa.py识别并加载由蟒,在执行期间,作为一个包的一部分。在这种情况下,该模块的名称faa.py将是例如some_packagename.faa。如果仅由于文件在当前目录中而被加载,则在运行python时,其名称将不会引用任何软件包,最终相对导入将失败。

引用当前目录中模块的一个简单解决方案是使用以下方法:

if __package__ is None or __package__ == '':
    # uses current directory visibility
    import foo
else:
    # uses current package visibility
    from . import foo

This is really a problem within python. The origin of confusion is that people mistakenly takes the relative import as path relative which is not.

For example when you write in faa.py:

from .. import foo

This has a meaning only if faa.py was identified and loaded by python, during execution, as a part of a package. In that case,the module’s name for faa.py would be for example some_packagename.faa. If the file was loaded just because it is in the current directory, when python is run, then its name would not refer to any package and eventually relative import would fail.

A simple solution to refer modules in the current directory, is to use this:

if __package__ is None or __package__ == '':
    # uses current directory visibility
    import foo
else:
    # uses current package visibility
    from . import foo

回答 2

这是一个通用的配方,经过修改以适合作为示例,我现在使用它来处理以程序包形式编写的Python库,其中包含相互依赖的文件,我希望能够逐个测试其中的某些部分。让我们称之为lib.foo它,它需要lib.fileA对函数f1f2lib.fileB类进行访问Class3

我打了几个print电话,以帮助说明这是如何工作的。实际上,您可能希望将其删除(也许还删除该from __future__ import print_function行)。

这个特定的例子太简单了,无法显示何时确实需要在中插入条目sys.path。(见拉尔斯的回答为我们的情况下,需要它,当我们有包目录中的两个或两个以上的水平,然后我们使用os.path.dirname(os.path.dirname(__file__))-但它并没有真正伤害在这里无论是。)它也足够安全要做到这一点,而不if _i in sys.path测试。但是,如果每个导入文件插入相同的路径-例如,如果两个fileAfileB希望导入实用程序从包中,这个杂波了sys.path具有相同路径很多次,所以很高兴有if _i not in sys.path在样板。

from __future__ import print_function # only when showing how this works

if __package__:
    print('Package named {!r}; __name__ is {!r}'.format(__package__, __name__))
    from .fileA import f1, f2
    from .fileB import Class3
else:
    print('Not a package; __name__ is {!r}'.format(__name__))
    # these next steps should be used only with care and if needed
    # (remove the sys.path manipulation for simple cases!)
    import os, sys
    _i = os.path.dirname(os.path.abspath(__file__))
    if _i not in sys.path:
        print('inserting {!r} into sys.path'.format(_i))
        sys.path.insert(0, _i)
    else:
        print('{!r} is already in sys.path'.format(_i))
    del _i # clean up global name space

    from fileA import f1, f2
    from fileB import Class3

... all the code as usual ...

if __name__ == '__main__':
    import doctest, sys
    ret = doctest.testmod()
    sys.exit(0 if ret.failed == 0 else 1)

这里的想法是这样的(请注意,这些在python2.7和python 3.x中的功能都相同):

  1. 如果从普通代码导入为常规软件包import libfrom lib import foo作为常规软件包运行,__package则is lib__name__is lib.foo。我们采用第一个代码路径,从.fileA等导入。

  2. 如果运行为python lib/foo.py__package__则将为None且__name__将为__main__

    我们采用第二条代码路径。该lib目录已经存在,sys.path因此无需添加它。我们从fileA等导入

  3. 如果在lib目录中以身份运行python foo.py,则其行为与情况2相同。

  4. 如果在libas目录中运行python -m foo,其行为类似于情况2和3。但是,lib目录的路径不在in中sys.path,因此我们在导入之前将其添加。如果我们先运行Python然后运行,则同样适用import foo

    (由于. sys.path,我们并不真正需要添加此路径的绝对的版本。这是一个更深层次的包嵌套结构,我们想要做的from ..otherlib.fileC import ...,有差别。如果你不这样做,就可以在sys.path完全省略所有操作。)

笔记

仍然有一个怪癖。如果从外部运行整个过程:

$ python2 lib.foo

要么:

$ python3 lib.foo

行为取决于的内容lib/__init__.py。如果存在并且为空,则一切正常:

Package named 'lib'; __name__ is '__main__'

但是,如果lib/__init__.py 本身导入,routine以便可以routine.name直接将导出为lib.name,则会得到:

$ python2 lib.foo
Package named 'lib'; __name__ is 'lib.foo'
Package named 'lib'; __name__ is '__main__'

也就是说,该模块两次导入,一次是通过包导入的,然后是再次导入的,__main__以便它运行您的main代码。Python 3.6及更高版本对此发出警告:

$ python3 lib.routine
Package named 'lib'; __name__ is 'lib.foo'
[...]/runpy.py:125: RuntimeWarning: 'lib.foo' found in sys.modules
after import of package 'lib', but prior to execution of 'lib.foo';
this may result in unpredictable behaviour
  warn(RuntimeWarning(msg))
Package named 'lib'; __name__ is '__main__'

警告是新的,但警告说,有关的行为是不能。这就是所谓的双重导入陷阱的一部分。(有关其他详细信息,请参见问题27487。)尼克·科格兰(Nick Coghlan)说:

下一个陷阱存在于所有当前的Python版本(包括3.3)中,并且可以在以下常规准则中进行总结:“切勿将包目录或包内的任何目录直接添加到Python路径中”。

请注意,虽然此处违反了该规则,但不将要加载的文件作为程序包的一部分加载时才这样做,并且我们的修改经过专门设计,允许我们访问该程序包中的其他文件。(而且,正如我所指出的,我们可能根本不应该为单层程序包执行此操作。)如果我们想变得更加干净,可以将其重写为例如:

    import os, sys
    _i = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    if _i not in sys.path:
        sys.path.insert(0, _i)
    else:
        _i = None

    from sub.fileA import f1, f2
    from sub.fileB import Class3

    if _i:
        sys.path.remove(_i)
    del _i

也就是说,我们进行了sys.path足够长的修改以实现导入,然后将其恢复原样(_i如果且仅当我们添加的一个副本时,删除一个副本_i)。

Here’s a general recipe, modified to fit as an example, that I am using right now for dealing with Python libraries written as packages, that contain interdependent files, where I want to be able to test parts of them piecemeal. Let’s call this lib.foo and say that it needs access to lib.fileA for functions f1 and f2, and lib.fileB for class Class3.

I have included a few print calls to help illustrate how this works. In practice you would want to remove them (and maybe also the from __future__ import print_function line).

This particular example is too simple to show when we really need to insert an entry into sys.path. (See Lars’ answer for a case where we do need it, when we have two or more levels of package directories, and then we use os.path.dirname(os.path.dirname(__file__))—but it doesn’t really hurt here either.) It’s also safe enough to do this without the if _i in sys.path test. However, if each imported file inserts the same path—for instance, if both fileA and fileB want to import utilities from the package—this clutters up sys.path with the same path many times, so it’s nice to have the if _i not in sys.path in the boilerplate.

from __future__ import print_function # only when showing how this works

if __package__:
    print('Package named {!r}; __name__ is {!r}'.format(__package__, __name__))
    from .fileA import f1, f2
    from .fileB import Class3
else:
    print('Not a package; __name__ is {!r}'.format(__name__))
    # these next steps should be used only with care and if needed
    # (remove the sys.path manipulation for simple cases!)
    import os, sys
    _i = os.path.dirname(os.path.abspath(__file__))
    if _i not in sys.path:
        print('inserting {!r} into sys.path'.format(_i))
        sys.path.insert(0, _i)
    else:
        print('{!r} is already in sys.path'.format(_i))
    del _i # clean up global name space

    from fileA import f1, f2
    from fileB import Class3

... all the code as usual ...

if __name__ == '__main__':
    import doctest, sys
    ret = doctest.testmod()
    sys.exit(0 if ret.failed == 0 else 1)

The idea here is this (and note that these all function the same across python2.7 and python 3.x):

  1. If run as import lib or from lib import foo as a regular package import from ordinary code, __package is lib and __name__ is lib.foo. We take the first code path, importing from .fileA, etc.

  2. If run as python lib/foo.py, __package__ will be None and __name__ will be __main__.

    We take the second code path. The lib directory will already be in sys.path so there is no need to add it. We import from fileA, etc.

  3. If run within the lib directory as python foo.py, the behavior is the same as for case 2.

  4. If run within the lib directory as python -m foo, the behavior is similar to cases 2 and 3. However, the path to the lib directory is not in sys.path, so we add it before importing. The same applies if we run Python and then import foo.

    (Since . is in sys.path, we don’t really need to add the absolute version of the path here. This is where a deeper package nesting structure, where we want to do from ..otherlib.fileC import ..., makes a difference. If you’re not doing this, you can omit all the sys.path manipulation entirely.)

Notes

There is still a quirk. If you run this whole thing from outside:

$ python2 lib.foo

or:

$ python3 lib.foo

the behavior depends on the contents of lib/__init__.py. If that exists and is empty, all is well:

Package named 'lib'; __name__ is '__main__'

But if lib/__init__.py itself imports routine so that it can export routine.name directly as lib.name, you get:

$ python2 lib.foo
Package named 'lib'; __name__ is 'lib.foo'
Package named 'lib'; __name__ is '__main__'

That is, the module gets imported twice, once via the package and then again as __main__ so that it runs your main code. Python 3.6 and later warn about this:

$ python3 lib.routine
Package named 'lib'; __name__ is 'lib.foo'
[...]/runpy.py:125: RuntimeWarning: 'lib.foo' found in sys.modules
after import of package 'lib', but prior to execution of 'lib.foo';
this may result in unpredictable behaviour
  warn(RuntimeWarning(msg))
Package named 'lib'; __name__ is '__main__'

The warning is new, but the warned-about behavior is not. It is part of what some call the double import trap. (For additional details see issue 27487.) Nick Coghlan says:

This next trap exists in all current versions of Python, including 3.3, and can be summed up in the following general guideline: “Never add a package directory, or any directory inside a package, directly to the Python path”.

Note that while we violate that rule here, we do it only when the file being loaded is not being loaded as part of a package, and our modification is specifically designed to allow us to access other files in that package. (And, as I noted, we probably shouldn’t do this at all for single level packages.) If we wanted to be extra-clean, we might rewrite this as, e.g.:

    import os, sys
    _i = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    if _i not in sys.path:
        sys.path.insert(0, _i)
    else:
        _i = None

    from sub.fileA import f1, f2
    from sub.fileB import Class3

    if _i:
        sys.path.remove(_i)
    del _i

That is, we modify sys.path long enough to achieve our imports, then put it back the way it was (deleting one copy of _i if and only if we added one copy of _i).


回答 3

因此,在与其他许多人讨论了这一问题之后,我遇到了Dorian B本文中发布的注释,该注释解决了我在开发与Web服务一起使用的模块和类时遇到的特定问题,但我也想成为能够使用PyCharm中的调试器工具在编写代码时对其进行测试。要在独立的类中运行测试,我将在类文件末尾包含以下内容:

if __name__ == '__main__':
   # run test code here...

但是如果我想在同一文件夹中导入其他类或模块,则必须将所有导入语句从相对符号更改为本地引用(即,删除点(。)。)但是在阅读了多里安的建议之后,我尝试了他的“一线”,它的工作!现在,我可以在PyCharm中进行测试,并在另一个被测类中使用该类时,或者在Web服务中使用该类时,将测试代码保留在原位!

# import any site-lib modules first, then...
import sys
parent_module = sys.modules['.'.join(__name__.split('.')[:-1]) or '__main__']
if __name__ == '__main__' or parent_module.__name__ == '__main__':
    from codex import Codex # these are in same folder as module under test!
    from dblogger import DbLogger
else:
    from .codex import Codex
    from .dblogger import DbLogger

if语句检查是否将这个模块作为main运行,或者是否在另一个被测试为main的模块中使用。也许这很明显,但是我在这里提供此说明,以防其他因上述相对导入问题而感到沮丧的人可以使用它。

So after carping about this along with many others, I came across a note posted by Dorian B in this article that solved the specific problem I was having where I would develop modules and classes for use with a web service, but I also want to be able to test them as I’m coding, using the debugger facilities in PyCharm. To run tests in a self-contained class, I would include the following at the end of my class file:

if __name__ == '__main__':
   # run test code here...

but if I wanted to import other classes or modules in the same folder, I would then have to change all my import statements from relative notation to local references (i.e. remove the dot (.)) But after reading Dorian’s suggestion, I tried his ‘one-liner’ and it worked! I can now test in PyCharm and leave my test code in place when I use the class in another class under test, or when I use it in my web service!

# import any site-lib modules first, then...
import sys
parent_module = sys.modules['.'.join(__name__.split('.')[:-1]) or '__main__']
if __name__ == '__main__' or parent_module.__name__ == '__main__':
    from codex import Codex # these are in same folder as module under test!
    from dblogger import DbLogger
else:
    from .codex import Codex
    from .dblogger import DbLogger

The if statement checks to see if we’re running this module as main or if it’s being used in another module that’s being tested as main. Perhaps this is obvious, but I offer this note here in case anyone else frustrated by the relative import issues above can make use of it.


回答 4

这是我不建议使用的一种解决方案,但在某些情况下可能根本不生成模块,这可能会很有用:

import os
import sys
parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(parent_dir_name + "/your_dir")
import your_script
your_script.a_function()

Here is one solution that I would not recommend, but might be useful in some situations where modules were simply not generated:

import os
import sys
parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(parent_dir_name + "/your_dir")
import your_script
your_script.a_function()

回答 5

我有一个类似的问题,我不想更改Python模块的搜索路径,而需要从脚本中相对地加载模块(尽管“脚本不能与所有对象相对地导入”,正如BrenBarn上面很好地解释的那样)。

因此,我使用了以下技巧。不幸的是,它依赖于imp从3.4版本开始就弃用的模块,而被取而代之importlib。(这是否也可以用importlib?我不知道。)不过,这种破解现在仍然有效。

从位于文件夹中的脚本访问moduleXin的成员的示例:subpackage1subpackage2

#!/usr/bin/env python3

import inspect
import imp
import os

def get_script_dir(follow_symlinks=True):
    """
    Return directory of code defining this very function.
    Should work from a module as well as from a script.
    """
    script_path = inspect.getabsfile(get_script_dir)
    if follow_symlinks:
        script_path = os.path.realpath(script_path)
    return os.path.dirname(script_path)

# loading the module (hack, relying on deprecated imp-module)
PARENT_PATH = os.path.dirname(get_script_dir())
(x_file, x_path, x_desc) = imp.find_module('moduleX', [PARENT_PATH+'/'+'subpackage1'])
module_x = imp.load_module('subpackage1.moduleX', x_file, x_path, x_desc)

# importing a function and a value
function = module_x.my_function
VALUE = module_x.MY_CONST

较干净的方法似乎是修改Federico提到的用于加载模块的sys.path。

#!/usr/bin/env python3

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    # __file__ should be defined in this case
    PARENT_DIR = path.dirname(path.dirname(path.abspath(__file__)))
   sys.path.append(PARENT_DIR)
from subpackage1.moduleX import *

I had a similar problem where I didn’t want to change the Python module search path and needed to load a module relatively from a script (in spite of “scripts can’t import relative with all” as BrenBarn explained nicely above).

So I used the following hack. Unfortunately, it relies on the imp module that became deprecated since version 3.4 to be dropped in favour of importlib. (Is this possible with importlib, too? I don’t know.) Still, the hack works for now.

Example for accessing members of moduleX in subpackage1 from a script residing in the subpackage2 folder:

#!/usr/bin/env python3

import inspect
import imp
import os

def get_script_dir(follow_symlinks=True):
    """
    Return directory of code defining this very function.
    Should work from a module as well as from a script.
    """
    script_path = inspect.getabsfile(get_script_dir)
    if follow_symlinks:
        script_path = os.path.realpath(script_path)
    return os.path.dirname(script_path)

# loading the module (hack, relying on deprecated imp-module)
PARENT_PATH = os.path.dirname(get_script_dir())
(x_file, x_path, x_desc) = imp.find_module('moduleX', [PARENT_PATH+'/'+'subpackage1'])
module_x = imp.load_module('subpackage1.moduleX', x_file, x_path, x_desc)

# importing a function and a value
function = module_x.my_function
VALUE = module_x.MY_CONST

A cleaner approach seems to be to modify the sys.path used for loading modules as mentioned by Federico.

#!/usr/bin/env python3

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    # __file__ should be defined in this case
    PARENT_DIR = path.dirname(path.dirname(path.abspath(__file__)))
   sys.path.append(PARENT_DIR)
from subpackage1.moduleX import *

回答 6

__name__ 更改取决于所讨论的代码是在全局命名空间中运行还是作为导入模块的一部分运行。

如果代码不在全局空间中运行,则为__name__模块名称。如果它在全局命名空间中运行-例如,如果您将其输入到控制台中,或者使用python.exe yourscriptnamehere.pythen __name__成为脚本来运行该模块"__main__"

您将看到很多if __name__ == '__main__'用于测试是否从全局命名空间运行代码的python代码 -这使您可以拥有一个兼用作脚本的模块。

您是否尝试过从控制台进行这些导入?

__name__ changes depending on whether the code in question is run in the global namespace or as part of an imported module.

If the code is not running in the global space, __name__ will be the name of the module. If it is running in global namespace — for example, if you type it into a console, or run the module as a script using python.exe yourscriptnamehere.py then __name__ becomes "__main__".

You’ll see a lot of python code with if __name__ == '__main__' is used to test whether the code is being run from the global namespace – that allows you to have a module that doubles as a script.

Did you try to do these imports from the console?


回答 7

@BrenBarn的回答说明了一切,但是如果您像我一样,可能需要一段时间才能理解。这是我的情况,以及@BrenBarn的答案如何适用于此,也许会对您有所帮助。

案子

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
    moduleA.py

使用我们熟悉的示例,并添加moduleX.py与..moduleA的相对导入。假设我尝试在导入moduleX的subpackage1目录中编写测试脚本,但随后得到了OP描述的可怕错误。

将测试脚本移至与package相同的级别,然后导入package.subpackage1.moduleX

说明

如前所述,相对导入是相对于当前名称进行的。当我的测试脚本从同一目录导入moduleX时,moduleX内的模块名称为moduleX。当遇到相对导入时,解释器无法备份程序包层次结构,因为它已经位于顶部

当我从上方导入moduleX时,moduleX内部的名称为package.subpackage1.moduleX,并且可以找到相对的导入

@BrenBarn’s answer says it all, but if you’re like me it might take a while to understand. Here’s my case and how @BrenBarn’s answer applies to it, perhaps it will help you.

The case

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
    moduleA.py

Using our familiar example, and add to it that moduleX.py has a relative import to ..moduleA. Given that I tried writing a test script in the subpackage1 directory that imported moduleX, but then got the dreaded error described by the OP.

Solution

Move test script to the same level as package and import package.subpackage1.moduleX

Explanation

As explained, relative imports are made relative to the current name. When my test script imports moduleX from the same directory, then module name inside moduleX is moduleX. When it encounters a relative import the interpreter can’t back up the package hierarchy because it’s already at the top

When I import moduleX from above, then name inside moduleX is package.subpackage1.moduleX and the relative import can be found


回答 8

相对导入使用模块的名称属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,将其设置为“ main”),则相对导入的解析就好像该模块是顶级模块一样,无论该模块实际位于文件系统上的哪个位置。

在PyPi上编写了一些python程序包,它可能会对这个问题的查看者有所帮助。如果一个人希望能够运行一个python文件,而该文件包含一个包/项目中的包含上层包的导入文件,而又不直接位于导入文件的目录中,则该包文件可以作为解决方法。https://pypi.org/project/import-anywhere/

Relative imports use a module’s name attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to ‘main’) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

Wrote a little python package to PyPi that might help viewers of this question. The package acts as workaround if one wishes to be able to run python files containing imports containing upper level packages from within a package / project without being directly in the importing file’s directory. https://pypi.org/project/import-anywhere/


回答 9

为了使Python不再返回我“尝试以非包方式进行相对导入”。包/

init .py subpackage1 / init .py moduleX.py moduleY.py subpackage2 / init .py moduleZ.py moduleA.py

仅当您将相对导入应用于父文件时,才会发生此错误。例如,在moduleA.py中对“ print(name)”进行编码后,父文件已经返回main,因此该文件已经是main它无法进一步返回任何父包。包subpackage1和subpackage2的文件中需要相对导入,您可以使用“ ..”来引用父目录或模块。但是parent是如果已经是顶级程序包,则它不能在该父目录(程序包)之上。您向父母应用相对导入的此类文件只能与绝对导入应用一起使用。如果您使用绝对导入到父程序包中将不会出现错误,因为PYTHON PATH的概念定义了项目的顶层,即使您的文件位于子程序包中,python也会知道谁在程序包的顶层

To make Python not return to me “Attempted relative import in non-package”. package/

init.py subpackage1/ init.py moduleX.py moduleY.py subpackage2/ init.py moduleZ.py moduleA.py

This error occurs only if you are applying relative import to the parent file. For example parent file already returns main after you code “print(name)” in moduleA.py .so THIS file is already main it cannot return any parent package further on. relative imports are required in files of packages subpackage1 and subpackage2 you can use “..” to refer to the parent directory or module .But parent is if already top level package it cannot go further above that parent directory(package). Such files where you are applying relative importing to parents can only work with the application of absolute import. If you will use ABSOLUTE IMPORT IN PARENT PACKAGE NO ERROR will come as python knows who is at the top level of package even if your file is in subpackages because of the concept of PYTHON PATH which defines the top level of the project