标签归档:package

相对导入-ModuleNotFoundError:没有名为x的模块

问题:相对导入-ModuleNotFoundError:没有名为x的模块

这是我第一次真正坐下来尝试python 3,但似乎失败了。我有以下两个文件:

  1. test.py
  2. config.py

config.py中定义了一些函数以及一些变量。我将其简化为以下内容:

config.py

debug = True

test.py

import config
print (config.debug)

我也有一个 __init__.py

但是,出现以下错误:

ModuleNotFoundError: No module named 'config'

我知道py3约定要使用绝对导入:

from . import config

但是,这导致以下错误:

ImportError: cannot import name 'config'

因此,我对此无所适从……任何帮助将不胜感激。:)

This is the first time I’ve really sat down and tried python 3, and seem to be failing miserably. I have the following two files:

  1. test.py
  2. config.py

config.py has a few functions defined in it as well as a few variables. I’ve stripped it down to the following:

config.py

debug = True

test.py

import config
print (config.debug)

I also have an __init__.py

However, I’m getting the following error:

ModuleNotFoundError: No module named 'config'

I’m aware that the py3 convention is to use absolute imports:

from . import config

However, this leads to the following error:

ImportError: cannot import name 'config'

So I’m at a loss as to what to do here… Any help is greatly appreciated. :)


回答 0

TL; DR:由于模块不是包的一部分,因此无法从执行的文件中进行相对导入__main__

绝对导入 -导入可用的内容sys.path

相对导入 -相对于当前模块的导入,必须是包的一部分

如果您以完全相同的方式运行两个变体,则其中一个应该可以工作。无论如何,这是一个示例,应该可以帮助您了解正在发生的事情,让我们添加main.py具有总体目录结构的另一个文件,如下所示:

.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py

让我们更新test.py以查看发生了什么:

# config.py
debug = True


# test.py
print(__name__)

try:
    # Trying to find module in the parent package
    from . import config
    print(config.debug)
    del config
except ImportError:
    print('Relative import failed')

try:
    # Trying to find module on sys.path
    import config
    print(config.debug)
except ModuleNotFoundError:
    print('Absolute import failed')
# main.py
import ryan.test

让我们先运行test.py:

$ python ryan/test.py
__main__
Relative import failed
True

这里的“测试” __main__模块,不知道属于什么包。但是import config应该可以,因为该ryan文件夹将被添加到sys.path中。

让我们运行main.py代替:

$ python main.py
ryan.test
True
Absolute import failed

这里的测试在“ ryan”包中,可以执行相对的导入。import config失败,因为Python 3中不允许隐式相对导入。

希望这会有所帮助。

PS:如果您坚持使用Python 3,则__init__.py文件中不再需要。

TL;DR: You can’t do relative imports from the file you execute since __main__ module is not a part of a package.

Absolute imports – import something available on sys.path

Relative imports – import something relative to the current module, must be a part of a package

If you’re running both variants in exactly the same way, one of them should work. Here is an example that should help you understand what’s going on. Let’s add another main.py file with the overall directory structure like this:

.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py

And let’s update test.py to see what’s going on:

# config.py
debug = True
# test.py
print(__name__)

try:
    # Trying to find module in the parent package
    from . import config
    print(config.debug)
    del config
except ImportError:
    print('Relative import failed')

try:
    # Trying to find module on sys.path
    import config
    print(config.debug)
except ModuleNotFoundError:
    print('Absolute import failed')
# main.py
import ryan.test

Let’s run test.py first:

$ python ryan/test.py
__main__
Relative import failed
True

Here “test” is the __main__ module and doesn’t know anything about belonging to a package. However import config should work, since the ryan folder will be added to sys.path.

Let’s run main.py instead:

$ python main.py
ryan.test
True
Absolute import failed

And here test is inside of the “ryan” package and can perform relative imports. import config fails since implicit relative imports are not allowed in Python 3.

Hope this helped.

P.S.: If you’re sticking with Python 3 there is no more need for __init__.py files.


回答 1

我想到了。非常令人沮丧,尤其是来自python2。

.无论模块是相对的还是绝对的,都必须向模块添加a 。

我创建目录设置如下。

/main.py
--/lib
  --/__init__.py
  --/mody.py
  --/modx.py

修改器

def does_something():
    return "I gave you this string."

from modx import does_something

def loaded():
    string = does_something()
    print(string)

main.py

from lib import mody

mody.loaded()

当我执行main时,会发生这种情况

$ python main.py
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from lib import mody
  File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
    from modx import does_something
ImportError: No module named 'modx'

我运行了2to3,核心输出是

RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something

 def loaded():
     string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py

我不得不修改mody.py的import语句来修复它

try:
    from modx import does_something
except ImportError:
    from .modx import does_something


def loaded():
    string = does_something()
    print(string)

然后我再次运行main.py并获得了预期的输出

$ python main.py
I gave you this string.

最后,只是清理一下并使其在2到3之间可移植。

from __future__ import absolute_import
from .modx import does_something

I figured it out. Very frustrating, especially coming from python2.

You have to add a . to the module, regardless of whether or not it is relative or absolute.

I created the directory setup as follows.

/main.py
--/lib
  --/__init__.py
  --/mody.py
  --/modx.py

modx.py

def does_something():
    return "I gave you this string."

mody.py

from modx import does_something

def loaded():
    string = does_something()
    print(string)

main.py

from lib import mody

mody.loaded()

when I execute main, this is what happens

$ python main.py
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from lib import mody
  File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
    from modx import does_something
ImportError: No module named 'modx'

I ran 2to3, and the core output was this

RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something

 def loaded():
     string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py

I had to modify mody.py’s import statement to fix it

try:
    from modx import does_something
except ImportError:
    from .modx import does_something


def loaded():
    string = does_something()
    print(string)

Then I ran main.py again and got the expected output

$ python main.py
I gave you this string.

Lastly, just to clean it up and make it portable between 2 and 3.

from __future__ import absolute_import
from .modx import does_something

回答 2

设置PYTHONPATH也可以解决此问题。

这是在Windows上可以完成的方法

set PYTHONPATH=.

Setting PYTHONPATH can also help with this problem.

Here is how it can be done on Windows

set PYTHONPATH=.


回答 3

您必须将模块的路径附加到PYTHONPATH


对于UNIX(Linux,OSX等)

export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"

对于Windows

set PYTHONPATH=%PYTHONPATH%;C:\path\to\your\module\

You have to append your project’s path to PYTHONPATH and make sure to use absolute imports.


For UNIX (Linux, OSX, …)

export PYTHONPATH="${PYTHONPATH}:/path/to/your/project/"

For Windows

set PYTHONPATH=%PYTHONPATH%;C:\path\to\your\project\

Absolute imports

Assuming that we have the following project structure,

└── myproject
    ├── mypackage
    │   ├── a.py
    └── anotherpackage
        ├── b.py
        ├── c.py
        └── mysubpackage
            └── d.py

just make sure to reference each import starting from the project’s root directory. For instance,

# in module a.py
import anotherpackage.mysubpackage.d

# in module b
import anotherpackage.c
import mypackage.a

回答 4

试过你的例子

from . import config

得到了以下SystemError:
/usr/bin/python3.4 test.py
Traceback(最近一次调用最近):
文件“ test.py”,第1行,位于
中。导入配置
SystemError:父模块“”未加载,无法执行相对导入


这对我有用:

import config
print('debug=%s'%config.debug)

>>>debug=True

使用Python:3.4.2测试-PyCharm 2016.3.2


除了此PyCharm,您还可以导入该名称
您必须单击,config然后出现帮助图标

Tried your example

from . import config

got the following SystemError:
/usr/bin/python3.4 test.py
Traceback (most recent call last):
File “test.py”, line 1, in
from . import config
SystemError: Parent module ” not loaded, cannot perform relative import


This will work for me:

import config
print('debug=%s'%config.debug)

>>>debug=True

Tested with Python:3.4.2 – PyCharm 2016.3.2


Beside this PyCharm offers you to Import this name.
You hav to click on config and a help icon appears.


回答 5

您只需将以下文件添加到测试目录中,然后python将在测试之前运行它

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

You can simply add following file to your tests directory, and then python will run it before the tests

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

回答 6

PYTHONPATH在根项目目录中设置环境变量。

考虑类UNIX:

export PYTHONPATH=.

Set PYTHONPATH environment variable in root project directory.

Considering UNIX-like:

export PYTHONPATH=.

回答 7

此示例在Python 3.6上有效。

我建议进入Run -> Edit ConfigurationsPyCharm,删除那里的所有条目,然后尝试再次通过PyCharm运行代码。

如果这不起作用,请检查项目解释器(“设置”->“项目解释器”)并运行默认配置(“运行”->“编辑配置…”)。

This example works on Python 3.6.

I suggest going to Run -> Edit Configurations in PyCharm, deleting any entries there, and trying to run the code through PyCharm again.

If that doesn’t work, check your project interpreter (Settings -> Project Interpreter) and run configuration defaults (Run -> Edit Configurations…).


回答 8

在调用模块之前,声明正确的sys.path列表:

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')

Declare correct sys.path list before you call module:

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')

回答 9

如原始帖子的评论中所述,这似乎是我出于任何原因使用的python解释器的问题,而不是python脚本出了点问题。我从WinPython包切换到了python.org上的官方python 3.6,它工作得很好。感谢大家的帮助:)

As was stated in the comments to the original post, this seemed to be an issue with the python interpreter I was using for whatever reason, and not something wrong with the python scripts. I switched over from the WinPython bundle to the official python 3.6 from python.org and it worked just fine. thanks for the help everyone :)


回答 10

如果您使用的是python 3+,请尝试添加以下行

import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)

If you are using python 3+ then try adding below lines

import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)

回答 11

尝试

from . import config

这是从同一文件夹级别导入的。如果您直接尝试导入,则假定它是下属

Try

from . import config

What that does is import from the same folder level. If you directly try to import it assumes it’s a subordinate


Pyinstaller-将Python程序打包为独立的可执行文件

PyInstaller概述

PyInstaller将Python应用程序及其所有依赖项捆绑到单个包中。用户无需安装Python解释器或任何模块即可运行打包的应用程序

文档: https://pyinstaller.readthedocs.io/
网站: http://www.pyinstaller.org/
代码: https://github.com/pyinstaller/pyinstaller

PyInstaller读取您编写的Python脚本。它分析您的代码以发现您的脚本执行所需的所有其他模块和库。然后,它会收集所有这些文件的副本–包括活动的Python解释器!–并将它们与脚本放在单个文件夹中,或者也可以放在单个可执行文件中

PyInstaller在Windows、MacOSX和GNU/Linux上进行了测试。但是,它不是交叉编译器:要制作Windows应用程序,您需要在Windows中运行PyInstaller;要制作GNU/Linux应用程序,需要在GNU/Linux等环境中运行它。PyInstaller已成功用于AIX、Solaris、FreeBSD和OpenBSD,但作为持续集成测试的一部分,没有针对它们进行测试

主要优势

  • 开箱即用,可与任何Python版本3.6-3.9配合使用
  • 完全多平台,利用操作系统支持加载动态库,确保完全兼容
  • 正确捆绑主要的Python包,如numpy、PyQt5、PySide2、Django、wxPython、matplotlib和其他开箱即用的包
  • 与许多开箱即用的第三方软件包兼容。(使外部包工作所需的所有技巧都已集成。)
  • 完全支持PyQt5、PySide2、wxPython、matplotlib或Django等库,无需手动处理插件或外部数据文件
  • 在OS X上使用代码签名
  • 在Windows上捆绑MS Visual C++DLL

安装

PyInstaller在PyPI上可用。您可以通过pip安装它:

pip install pyinstaller

要求和测试平台

  • 巨蟒:
  • 3.6-3.9
  • tinyaes1.0+(仅当使用字节码加密时)。与其安装天鹅座,pip install pyinstaller[encryption]取而代之的是
  • Windows(32位/64位):
  • PyInstaller应该可以在Windows 7或更新版本上运行,但我们只正式支持Windows 8+
  • 由于以下原因,当不使用虚拟环境时,我们不支持从Windows商店安装Pythonpermission errors那不是很容易修好的
  • GNU/Linux(32位/64位)
  • LDD:用于打印每个程序或共享库所需共享库的控制台应用程序。这通常可以在分发包glibc或libc-bin中找到
  • objdump:显示对象文件信息的控制台应用程序。这通常可以在分发包的binutils中找到
  • objcopy:复制和翻译目标文件的控制台应用程序。这通常也可以在分发包的binutils中找到
  • Mac OS X(64位):
  • Mac OS X 10.13(High Sierra)或更高版本

用法

基本用法非常简单,只需针对您的主脚本运行即可:

pyinstaller /path/to/yourscript.py

有关更多详细信息,请参阅manual

未经测试的平台

已经贡献了以下平台,欢迎对这些平台进行任何反馈或增强

  • FreeBSD
  • LDD
  • Solaris
  • LDD
  • 对象转储
  • AIX
  • AIX 6.1或更高版本。PyInstaller不能使用静态链接的Python库
  • LDD
  • PowerPC GNU/Linux(Debian)

在使用任何贡献的平台之前,您需要构建PyInstaller引导加载器,因为我们不提供二进制包。下载PyInstaller源代码,并构建引导加载器:

cd bootloader
python ./waf all

然后安装PyInstaller:

python setup.py install

或者直接从源代码(pyinstaller.py)使用它

支持

看见http://www.pyinstaller.org/support.html有关如何获得帮助以及商业支持的信息

此版本中的更改

您可以在以下位置找到此版本中更改的详细列表Changelog手册的一节

Python 3:ImportError“没有名为Setuptools的模块”

问题:Python 3:ImportError“没有名为Setuptools的模块”

我在使用Python 3安装软件包时遇到了麻烦。

我一直都使用来安装软件包setup.py install。但是现在,当我尝试安装ansicolors软件包时,我得到了:

importerror“没有名为Setuptools的模块”

我不知道该怎么办,因为过去我没有安装过setuptools。尽管如此,我仍然能够在setup.py install没有setuptools的情况下安装许多软件包。为什么现在应该获得setuptools?

我什至无法安装setuptools,因为我有Python 3.3,setuptools不支持Python 3。

为什么我的安装命令不再起作用?

I’m having troubles with installing packages in Python 3.

I have always installed packages with setup.py install. But now, when I try to install the ansicolors package I get:

importerror “No Module named Setuptools”

I have no idea what to do because I didn’t have setuptools installed in the past. Still, I was able to install many packages with setup.py install without setuptools. Why should I get setuptools now?

I can’t even install setuptools because I have Python 3.3 and setuptools doesn’t support Python 3.

Why doesn’t my install command work anymore?


回答 0

您的setup.py文件需要setuptools。一些Python软件包曾经distutils用于分发,但现在大多数都使用setuptools了一个更完整的软件包。是有关它们之间差异的问题。

setuptools在Debian上安装:

sudo apt-get install python3-setuptools

对于旧版本的Python(Python 2.x):

sudo apt-get install python-setuptools

Your setup.py file needs setuptools. Some Python packages used to use distutils for distribution, but most now use setuptools, a more complete package. Here is a question about the differences between them.

To install setuptools on Debian:

sudo apt-get install python3-setuptools

For an older version of Python (Python 2.x):

sudo apt-get install python-setuptools

回答 1

编辑:官方setuptools dox页面

如果您从python.org安装了Python 2> = 2.7.9或Python 3> = 3.4,则已经具有pip和setuptools,但需要升级到最新版本:

在Linux或OS X上:

pip install -U pip setuptools 

在Windows上:

python -m pip install -U pip setuptools

因此,本文的其余部分可能已过时(例如,某些链接不起作用)。

分发 -是setuptools分支,可“提供Python 3支持”。Distribution(setuptools)+ pip的安装说明:

curl -O http://python-distribute.org/distribute_setup.py
python distribute_setup.py
easy_install pip

这里有类似的问题。

更新:分发似乎已过时,即已合并到Setuptools中:分发是Setuptools项目不推荐使用的分支。从Setuptools 0.7发行版开始,Setuptools和Distribute已合并,并且不再维护Distribute。所有正在进行的工作应参考Setuptools项目和Setuptools文档。

您可以尝试在setuptools pypi页面上找到说明(我尚未对此进行测试,对不起:():

wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python
easy_install pip

EDIT: Official setuptools dox page:

If you have Python 2 >=2.7.9 or Python 3 >=3.4 installed from python.org, you will already have pip and setuptools, but will need to upgrade to the latest version:

On Linux or OS X:

pip install -U pip setuptools 

On Windows:

python -m pip install -U pip setuptools

Therefore the rest of this post is probably obsolete (e.g. some links don’t work).

Distribute – is a setuptools fork which “offers Python 3 support”. Installation instructions for distribute(setuptools) + pip:

curl -O http://python-distribute.org/distribute_setup.py
python distribute_setup.py
easy_install pip

Similar issue here.

UPDATE: Distribute seems to be obsolete, i.e. merged into Setuptools: Distribute is a deprecated fork of the Setuptools project. Since the Setuptools 0.7 release, Setuptools and Distribute have merged and Distribute is no longer being maintained. All ongoing effort should reference the Setuptools project and the Setuptools documentation.

You may try with instructions found on setuptools pypi page (I haven’t tested this, sorry :( ):

wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python
easy_install pip

回答 2

我在使用python-2.6的Oracle Linux 6.4上的virtualenv内执行此操作,因此基于apt的解决方案对我来说不是一个选择,python-2.7的想法也不对。我的解决方法是升级我由virtualenv安装的setuptools版本:

pip install --upgrade setuptools

之后,我能够将软件包安装到virtualenv中。我知道这个问题已经选择了答案,但我希望这个答案对我的情况有所帮助。

I was doing this inside a virtualenv on Oracle Linux 6.4 using python-2.6 so the apt-based solutions weren’t an option for me, nor were the python-2.7 ideas. My fix was to upgrade my version of setuptools that had been installed by virtualenv:

pip install --upgrade setuptools

After that, I was able to install packages into the virtualenv. I know this question has already had an answer selected but I hope this answer will help others in my situation.


回答 3

pip uninstall setuptools

然后:

pip install setuptools

这对我有用,并解决了我的问题。

pip uninstall setuptools

and then:

pip install setuptools

This works for me and fix my issue.


回答 4

distribute软件包提供了与Python 3兼容的版本setuptoolshttp : //pypi.python.org/pypi/distribute

另外,用于pip安装模块。它会自动找到依赖项并为您安装它们。

对于您的包裹,它对我来说效果很好:

[~] pip --version                                                              
pip 1.2.1 from /usr/lib/python3.3/site-packages (python 3.3)
[~] sudo pip install ansicolors                                                
Downloading/unpacking ansicolors
  Downloading ansicolors-1.0.2.tar.gz
  Running setup.py egg_info for package ansicolors

Installing collected packages: ansicolors
  Running setup.py install for ansicolors

Successfully installed ansicolors
Cleaning up...
[~]

The distribute package provides a Python 3-compatible version of setuptools: http://pypi.python.org/pypi/distribute

Also, use pip to install the modules. It automatically finds dependencies and installs them for you.

It works just fine for me with your package:

[~] pip --version                                                              
pip 1.2.1 from /usr/lib/python3.3/site-packages (python 3.3)
[~] sudo pip install ansicolors                                                
Downloading/unpacking ansicolors
  Downloading ansicolors-1.0.2.tar.gz
  Running setup.py egg_info for package ansicolors

Installing collected packages: ansicolors
  Running setup.py install for ansicolors

Successfully installed ansicolors
Cleaning up...
[~]

回答 5

Windows 7的:

我在这里为python selenium webdriver 提供了完整的解决方案

1. Setup easy install (windows - simplified)
    a. download ez.setup.py (https://bootstrap.pypa.io/ez_setup.py) from 'https://pypi.python.org/pypi/setuptools'
    b. move ez.setup.py to C:\Python27\
    c. open cmd prompt
    d. cd C:\Python27\
    e. C:\Python27\python.exe ez.setup.py install

Windows 7:

I have given a complete solution here for python selenium webdriver

1. Setup easy install (windows - simplified)
    a. download ez.setup.py (https://bootstrap.pypa.io/ez_setup.py) from 'https://pypi.python.org/pypi/setuptools'
    b. move ez.setup.py to C:\Python27\
    c. open cmd prompt
    d. cd C:\Python27\
    e. C:\Python27\python.exe ez.setup.py install

回答 6

PyPA推荐的用于安装和管理Python包的工具pippip包括在Python 3.4(PEP 453),但对于旧版本这里是如何安装它(在Windows上):

下载https://bootstrap.pypa.io/get-pip.py

>c:\Python33\python.exe get-pip.py
Downloading/unpacking pip
Downloading/unpacking setuptools
Installing collected packages: pip, setuptools
Successfully installed pip setuptools
Cleaning up...

>c:\Python33\Scripts\pip.exe install pymysql
Downloading/unpacking pymysql
Installing collected packages: pymysql
Successfully installed pymysql
Cleaning up...

The PyPA recommended tool for installing and managing Python packages is pip. pip is included with Python 3.4 (PEP 453), but for older versions here’s how to install it (on Windows):

Download https://bootstrap.pypa.io/get-pip.py

>c:\Python33\python.exe get-pip.py
Downloading/unpacking pip
Downloading/unpacking setuptools
Installing collected packages: pip, setuptools
Successfully installed pip setuptools
Cleaning up...

>c:\Python33\Scripts\pip.exe install pymysql
Downloading/unpacking pymysql
Installing collected packages: pymysql
Successfully installed pymysql
Cleaning up...

回答 7

几年前,我继承了在Django-1.2.3下运行的python(2.7.1)项目,现在被要求使用QR增强功能。遇到了同样的问题,没有找到pip或apt-get。所以我以完全不同但简单的方式解决了它。我/ bin / vi-ed setup.py,并将“ from setuptools import setup”这一行更改为:“ from distutils.core import setup”对我而言,所以我认为我应该将它发布给其他运行旧python的用户。问候,罗杰·维米尔

A few years ago I inherited a python (2.7.1) project running under Django-1.2.3 and now was asked to enhance it with QR possibilities. Got the same problem and did not find pip or apt-get either. So I solved it in a totally different but easy way. I /bin/vi-ed the setup.py and changed the line “from setuptools import setup” into: “from distutils.core import setup” That did it for me, so I thought I should post this for other users running old pythons. Regards, Roger Vermeir


将版本嵌入python包的标准方法?

问题:将版本嵌入python包的标准方法?

有没有一种标准的方式可以将版本字符串与python软件包相关联,从而可以执行以下操作?

import foo
print foo.version

我可以想象有某种方法可以检索数据而无需任何额外的硬编码,因为setup.py已经指定了次要/主要字符串。另一种解决方案,我发现是有import __version__我的foo/__init__.py,然后让__version__.py所产生的setup.py

Is there a standard way to associate version string with a python package in such way that I could do the following?

import foo
print foo.version

I would imagine there’s some way to retrieve that data without any extra hardcoding, since minor/major strings are specified in setup.py already. Alternative solution that I found was to have import __version__ in my foo/__init__.py and then have __version__.py generated by setup.py.


回答 0

不是直接回答您的问题,而是您应该考虑命名它__version__,而不是version

这几乎是一个准标准。标准库中的许多模块都使用__version__,并且在许多第三方模块中也使用了它,因此它是准标准的。

通常,它__version__是一个字符串,但有时它也是一个浮点数或元组。

编辑:正如S.Lott所提到的(谢谢!),PEP 8明确表示:

模块级Dunder名称

模块级“dunders”(即名称具有两个前缘和两个纵下划线),例如__all____author____version__等应被放置在模块文档字符串之后,但在除了从任何导入语句__future__进口。

您还应确保版本号符合PEP 440中描述的格式(PEP 386是该标准的先前版本)。

Not directly an answer to your question, but you should consider naming it __version__, not version.

This is almost a quasi-standard. Many modules in the standard library use __version__, and this is also used in lots of 3rd-party modules, so it’s the quasi-standard.

Usually, __version__ is a string, but sometimes it’s also a float or tuple.

Edit: as mentioned by S.Lott (Thank you!), PEP 8 says it explicitly:

Module Level Dunder Names

Module level “dunders” (i.e. names with two leading and two trailing underscores) such as __all__, __author__, __version__, etc. should be placed after the module docstring but before any import statements except from __future__ imports.

You should also make sure that the version number conforms to the format described in PEP 440 (PEP 386 a previous version of this standard).


回答 1

我使用一个_version.py文件作为“一次规范的位置”来存储版本信息:

  1. 它提供了一个__version__属性。

  2. 它提供了标准的元数据版本。因此,它将由pkg_resources解析包元数据的其他工具(EGG-INFO和/或PKG-INFO,PEP 0345)检测到。

  3. 在构建软件包时,它不会导入您的软件包(或其他任何东西),这在某些情况下可能会导致问题。(请参阅下面的评论,这可能会导致什么问题。)

  4. 写下版本号的位置只有一个,因此,当版本号更改时,只有一个地方可以更改版本号,并且版本不一致的可能性较小。

它是这样工作的:存储版本号的“一个规范位置”是一个.py文件,名为“ _version.py”,位于您的Python软件包中,例如myniftyapp/_version.py。该文件是Python模块,但您的setup.py不会导入它!(这会使功能3失效。)相反,setup.py知道此文件的内容非常简单,类似于:

__version__ = "3.6.5"

因此,您的setup.py将使用以下代码打开文件并对其进行解析:

import re
VERSIONFILE="myniftyapp/_version.py"
verstrline = open(VERSIONFILE, "rt").read()
VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
mo = re.search(VSRE, verstrline, re.M)
if mo:
    verstr = mo.group(1)
else:
    raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))

然后,您的setup.py将该字符串作为“ version”参数的值传递给setup(),从而满足功能2的要求。

为了满足功能1,您可以让包(在运行时,而不是在安装时!)从_version文件中导入,myniftyapp/__init__.py如下所示:

from _version import __version__

这是我使用多年的这种技术的示例

该示例中的代码稍微复杂一点,但是我在此注释中编写的简化示例应该是完整的实现。

这是导入版本的示例代码

如果您发现此方法有任何问题,请告诉我。

I use a single _version.py file as the “once cannonical place” to store version information:

  1. It provides a __version__ attribute.

  2. It provides the standard metadata version. Therefore it will be detected by pkg_resources or other tools that parse the package metadata (EGG-INFO and/or PKG-INFO, PEP 0345).

  3. It doesn’t import your package (or anything else) when building your package, which can cause problems in some situations. (See the comments below about what problems this can cause.)

  4. There is only one place that the version number is written down, so there is only one place to change it when the version number changes, and there is less chance of inconsistent versions.

Here is how it works: the “one canonical place” to store the version number is a .py file, named “_version.py” which is in your Python package, for example in myniftyapp/_version.py. This file is a Python module, but your setup.py doesn’t import it! (That would defeat feature 3.) Instead your setup.py knows that the contents of this file is very simple, something like:

__version__ = "3.6.5"

And so your setup.py opens the file and parses it, with code like:

import re
VERSIONFILE="myniftyapp/_version.py"
verstrline = open(VERSIONFILE, "rt").read()
VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
mo = re.search(VSRE, verstrline, re.M)
if mo:
    verstr = mo.group(1)
else:
    raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))

Then your setup.py passes that string as the value of the “version” argument to setup(), thus satisfying feature 2.

To satisfy feature 1, you can have your package (at run-time, not at setup time!) import the _version file from myniftyapp/__init__.py like this:

from _version import __version__

Here is an example of this technique that I’ve been using for years.

The code in that example is a bit more complicated, but the simplified example that I wrote into this comment should be a complete implementation.

Here is example code of importing the version.

If you see anything wrong with this approach, please let me know.


回答 2

改写2017-05

经过十多年的编写Python代码和管理各种程序包的经历,我得出的结论是,DIY可能不是最好的方法。

我开始使用pbr软件包来处理软件包中的版本控制。如果您将git用作SCM,它将像魔术一样适合您的工作流程,从而节省了数周的工作(您可能会对问题的复杂程度感到惊讶)。

截至目前,pbr在最常用的python软件包中排名第11,并且达到这一水平还没有任何肮脏的技巧:仅仅是一个:用一种非常简单的方法解决了常见的包装问题。

pbr 可以承担更多的程序包维护负担,不仅限于版本控制,还不强迫您采用其所有优点。

因此,为了让您了解一次提交中采用pbr的外观,请看一下将包装夹到pbr

可能您会发现该版本根本没有存储在存储库中。PBR确实从Git分支和标签中检测到它。

无需担心没有git存储库时会发生什么情况,因为打包或安装应用程序时pbr会“编译”并缓存版本,因此git没有运行时依赖性。

旧解决方案

这是到目前为止我所见过的最好的解决方案,它也解释了原因:

内部yourpackage/version.py

# Store the version here so:
# 1) we don't load dependencies by storing it in __init__.py
# 2) we can import it in setup.py for the same reason
# 3) we can import it into your module module
__version__ = '0.12'

内部yourpackage/__init__.py

from .version import __version__

内部setup.py

exec(open('yourpackage/version.py').read())
setup(
    ...
    version=__version__,
    ...

如果您知道另一种似乎更好的方法,请告诉我。

Rewritten 2017-05

After 13+ years of writing Python code and managing various packages, I came to the conclusion that DIY is maybe not the best approach.

I started using the pbr package for dealing with versioning in my packages. If you are using git as your SCM, this will fit into your workflow like magic, saving your weeks of work (you will be surprised about how complex the issue can be).

As of today, pbr is the 11th most used python package, and reaching this level didn’t include any dirty tricks. It was only one thing — fixing a common packaging problem in a very simple way.

pbr can do more of the package maintenance burden, and is not limited to versioning, but it does not force you to adopt all its benefits.

So to give you an idea about how it looks to adopt pbr in one commit have a look switching packaging to pbr

Probably you would observed that the version is not stored at all in the repository. PBR does detect it from Git branches and tags.

No need to worry about what happens when you do not have a git repository because pbr does “compile” and cache the version when you package or install the applications, so there is no runtime dependency on git.

Old solution

Here is the best solution I’ve seen so far and it also explains why:

Inside yourpackage/version.py:

# Store the version here so:
# 1) we don't load dependencies by storing it in __init__.py
# 2) we can import it in setup.py for the same reason
# 3) we can import it into your module module
__version__ = '0.12'

Inside yourpackage/__init__.py:

from .version import __version__

Inside setup.py:

exec(open('yourpackage/version.py').read())
setup(
    ...
    version=__version__,
    ...

If you know another approach that seems to be better let me know.


回答 3

根据递延的PEP 396(模块版本号),有一种建议的方法。它从原理上描述了要遵循的模块的一个(公认的可选)标准。这是一个片段:

3)当一个模块(或包)包括一个版本号时,该版本应该在__version__属性中可用。

4)对于位于命名空间包中的模块,该模块应包含该__version__属性。命名空间包本身不应包含其自己的__version__属性。

5)__version__属性的值应该是一个字符串。

Per the deferred PEP 396 (Module Version Numbers), there is a proposed way to do this. It describes, with rationale, an (admittedly optional) standard for modules to follow. Here’s a snippet:

3) When a module (or package) includes a version number, the version SHOULD be available in the __version__ attribute.

4) For modules which live inside a namespace package, the module SHOULD include the __version__ attribute. The namespace package itself SHOULD NOT include its own __version__ attribute.

5) The __version__ attribute’s value SHOULD be a string.


回答 4

尽管这可能为时已晚,但是对于先前的答案有一个稍微简单的替代方法:

__version_info__ = ('1', '2', '3')
__version__ = '.'.join(__version_info__)

(使用来将版本号的自动递增部分转换为字符串将是非常简单的str()。)

当然,据我所见,人们在使用时通常会使用类似先前提到的版本__version_info__,并将其存储为int元组;但是,我不太明白这样做的意义,因为我怀疑在某些情况下您会出于好奇或自动递增的目的而出于任何目的对版本号的某些部分执行数学运算,例如对版本号进行加减运算(即使如此,int()并且str()可以很容易地使用)。(另一方面,其他人的代码可能期望数字元组而不是字符串元组,从而导致失败。)

当然,这是我自己的观点,我很高兴希望其他人使用数字元组提供输入。


正如shezi提醒我的那样,数字字符串的(词法)比较不一定具有与直接数字比较相同的结果;为此,将需要前导零。因此,最后,将__version_info__(或将要调用的任何形式)存储为整数值的元组将允许更有效的版本比较。

Though this is probably far too late, there is a slightly simpler alternative to the previous answer:

__version_info__ = ('1', '2', '3')
__version__ = '.'.join(__version_info__)

(And it would be fairly simple to convert auto-incrementing portions of version numbers to a string using str().)

Of course, from what I’ve seen, people tend to use something like the previously-mentioned version when using __version_info__, and as such store it as a tuple of ints; however, I don’t quite see the point in doing so, as I doubt there are situations where you would perform mathematical operations such as addition and subtraction on portions of version numbers for any purpose besides curiosity or auto-incrementation (and even then, int() and str() can be used fairly easily). (On the other hand, there is the possibility of someone else’s code expecting a numerical tuple rather than a string tuple and thus failing.)

This is, of course, my own view, and I would gladly like others’ input on using a numerical tuple.


As shezi reminded me, (lexical) comparisons of number strings do not necessarily have the same result as direct numerical comparisons; leading zeroes would be required to provide for that. So in the end, storing __version_info__ (or whatever it would be called) as a tuple of integer values would allow for more efficient version comparisons.


回答 5

这里的许多解决方案都忽略了git版本标记,这仍然意味着您必须在多个位置跟踪版本(错误)。我通过以下目标实现了这一目标:

  • 派生的从标签的所有Python版本引用git回购
  • 使用一个无需输入的命令自动执行git tag/ pushsetup.py upload步骤。

这个怎么运作:

  1. make release命令中,找到并递增git repo中的最后一个标记版本。标签被推回到origin

  2. Makefile存储的版本在src/_version.py那里将被读取setup.py,并且还包含在释放。不要检_version.py入源代码管理!

  3. setup.py命令从中读取新版本字符串package.__version__

细节:

生成文件

# remove optional 'v' and trailing hash "v1.0-N-HASH" -> "v1.0-N"
git_describe_ver = $(shell git describe --tags | sed -E -e 's/^v//' -e 's/(.*)-.*/\1/')
git_tag_ver      = $(shell git describe --abbrev=0)
next_patch_ver = $(shell python versionbump.py --patch $(call git_tag_ver))
next_minor_ver = $(shell python versionbump.py --minor $(call git_tag_ver))
next_major_ver = $(shell python versionbump.py --major $(call git_tag_ver))

.PHONY: ${MODULE}/_version.py
${MODULE}/_version.py:
    echo '__version__ = "$(call git_describe_ver)"' > $@

.PHONY: release
release: test lint mypy
    git tag -a $(call next_patch_ver)
    $(MAKE) ${MODULE}/_version.py
    python setup.py check sdist upload # (legacy "upload" method)
    # twine upload dist/*  (preferred method)
    git push origin master --tags

release目标总是递增第三版数字,但可以使用next_minor_vernext_major_ver递增其他数字。这些命令依赖于versionbump.py签入仓库根目录的脚本

versionbump.py

"""An auto-increment tool for version strings."""

import sys
import unittest

import click
from click.testing import CliRunner  # type: ignore

__version__ = '0.1'

MIN_DIGITS = 2
MAX_DIGITS = 3


@click.command()
@click.argument('version')
@click.option('--major', 'bump_idx', flag_value=0, help='Increment major number.')
@click.option('--minor', 'bump_idx', flag_value=1, help='Increment minor number.')
@click.option('--patch', 'bump_idx', flag_value=2, default=True, help='Increment patch number.')
def cli(version: str, bump_idx: int) -> None:
    """Bumps a MAJOR.MINOR.PATCH version string at the specified index location or 'patch' digit. An
    optional 'v' prefix is allowed and will be included in the output if found."""
    prefix = version[0] if version[0].isalpha() else ''
    digits = version.lower().lstrip('v').split('.')

    if len(digits) > MAX_DIGITS:
        click.secho('ERROR: Too many digits', fg='red', err=True)
        sys.exit(1)

    digits = (digits + ['0'] * MAX_DIGITS)[:MAX_DIGITS]  # Extend total digits to max.
    digits[bump_idx] = str(int(digits[bump_idx]) + 1)  # Increment the desired digit.

    # Zero rightmost digits after bump position.
    for i in range(bump_idx + 1, MAX_DIGITS):
        digits[i] = '0'
    digits = digits[:max(MIN_DIGITS, bump_idx + 1)]  # Trim rightmost digits.
    click.echo(prefix + '.'.join(digits), nl=False)


if __name__ == '__main__':
    cli()  # pylint: disable=no-value-for-parameter

这对于如何处理和增加版本号起了很大的作用git

__init__.py

my_module/_version.py文件已导入my_module/__init__.py。将要与模块一起分发的所有静态安装配置放在此处。

from ._version import __version__
__author__ = ''
__email__ = ''

setup.py

最后一步是从my_module模块读取版本信息。

from setuptools import setup, find_packages

pkg_vars  = {}

with open("{MODULE}/_version.py") as fp:
    exec(fp.read(), pkg_vars)

setup(
    version=pkg_vars['__version__'],
    ...
    ...
)

当然,要使所有这些都起作用,您必须在存储库中至少有一个版本标签才能启动。

git tag -a v0.0.1

Many of these solutions here ignore git version tags which still means you have to track version in multiple places (bad). I approached this with the following goals:

  • Derive all python version references from a tag in the git repo
  • Automate git tag/push and setup.py upload steps with a single command that takes no inputs.

How it works:

  1. From a make release command, the last tagged version in the git repo is found and incremented. The tag is pushed back to origin.

  2. The Makefile stores the version in src/_version.py where it will be read by setup.py and also included in the release. Do not check _version.py into source control!

  3. setup.py command reads the new version string from package.__version__.

Details:

Makefile

# remove optional 'v' and trailing hash "v1.0-N-HASH" -> "v1.0-N"
git_describe_ver = $(shell git describe --tags | sed -E -e 's/^v//' -e 's/(.*)-.*/\1/')
git_tag_ver      = $(shell git describe --abbrev=0)
next_patch_ver = $(shell python versionbump.py --patch $(call git_tag_ver))
next_minor_ver = $(shell python versionbump.py --minor $(call git_tag_ver))
next_major_ver = $(shell python versionbump.py --major $(call git_tag_ver))

.PHONY: ${MODULE}/_version.py
${MODULE}/_version.py:
    echo '__version__ = "$(call git_describe_ver)"' > $@

.PHONY: release
release: test lint mypy
    git tag -a $(call next_patch_ver)
    $(MAKE) ${MODULE}/_version.py
    python setup.py check sdist upload # (legacy "upload" method)
    # twine upload dist/*  (preferred method)
    git push origin master --tags

The release target always increments the 3rd version digit, but you can use the next_minor_ver or next_major_ver to increment the other digits. The commands rely on the versionbump.py script that is checked into the root of the repo

versionbump.py

"""An auto-increment tool for version strings."""

import sys
import unittest

import click
from click.testing import CliRunner  # type: ignore

__version__ = '0.1'

MIN_DIGITS = 2
MAX_DIGITS = 3


@click.command()
@click.argument('version')
@click.option('--major', 'bump_idx', flag_value=0, help='Increment major number.')
@click.option('--minor', 'bump_idx', flag_value=1, help='Increment minor number.')
@click.option('--patch', 'bump_idx', flag_value=2, default=True, help='Increment patch number.')
def cli(version: str, bump_idx: int) -> None:
    """Bumps a MAJOR.MINOR.PATCH version string at the specified index location or 'patch' digit. An
    optional 'v' prefix is allowed and will be included in the output if found."""
    prefix = version[0] if version[0].isalpha() else ''
    digits = version.lower().lstrip('v').split('.')

    if len(digits) > MAX_DIGITS:
        click.secho('ERROR: Too many digits', fg='red', err=True)
        sys.exit(1)

    digits = (digits + ['0'] * MAX_DIGITS)[:MAX_DIGITS]  # Extend total digits to max.
    digits[bump_idx] = str(int(digits[bump_idx]) + 1)  # Increment the desired digit.

    # Zero rightmost digits after bump position.
    for i in range(bump_idx + 1, MAX_DIGITS):
        digits[i] = '0'
    digits = digits[:max(MIN_DIGITS, bump_idx + 1)]  # Trim rightmost digits.
    click.echo(prefix + '.'.join(digits), nl=False)


if __name__ == '__main__':
    cli()  # pylint: disable=no-value-for-parameter

This does the heavy lifting how to process and increment the version number from git.

__init__.py

The my_module/_version.py file is imported into my_module/__init__.py. Put any static install config here that you want distributed with your module.

from ._version import __version__
__author__ = ''
__email__ = ''

setup.py

The last step is to read the version info from the my_module module.

from setuptools import setup, find_packages

pkg_vars  = {}

with open("{MODULE}/_version.py") as fp:
    exec(fp.read(), pkg_vars)

setup(
    version=pkg_vars['__version__'],
    ...
    ...
)

Of course, for all of this to work you’ll have to have at least one version tag in your repo to start.

git tag -a v0.0.1

回答 6

我在包目录中使用JSON文件。这符合Zooko的要求。

内部pkg_dir/pkg_info.json

{"version": "0.1.0"}

内部setup.py

from distutils.core import setup
import json

with open('pkg_dir/pkg_info.json') as fp:
    _info = json.load(fp)

setup(
    version=_info['version'],
    ...
    )

内部pkg_dir/__init__.py

import json
from os.path import dirname

with open(dirname(__file__) + '/pkg_info.json') as fp:
    _info = json.load(fp)

__version__ = _info['version']

我还把其他信息放进pkg_info.json,例如作者。我喜欢使用JSON,因为我可以自动管理元数据。

I use a JSON file in the package dir. This fits Zooko’s requirements.

Inside pkg_dir/pkg_info.json:

{"version": "0.1.0"}

Inside setup.py:

from distutils.core import setup
import json

with open('pkg_dir/pkg_info.json') as fp:
    _info = json.load(fp)

setup(
    version=_info['version'],
    ...
    )

Inside pkg_dir/__init__.py:

import json
from os.path import dirname

with open(dirname(__file__) + '/pkg_info.json') as fp:
    _info = json.load(fp)

__version__ = _info['version']

I also put other information in pkg_info.json, like author. I like to use JSON because I can automate management of metadata.


回答 7

同样值得一提的是,它还__version__具有半标准性。在python中,__version_info__这是一个元组,在简单的情况下,您可以执行以下操作:

__version__ = '1.2.3'
__version_info__ = tuple([ int(num) for num in __version__.split('.')])

…您可以__version__从文件或任何其他内容中获取字符串。

Also worth noting is that as well as __version__ being a semi-std. in python so is __version_info__ which is a tuple, in the simple cases you can just do something like:

__version__ = '1.2.3'
__version_info__ = tuple([ int(num) for num in __version__.split('.')])

…and you can get the __version__ string from a file, or whatever.


回答 8

似乎没有一种将版本字符串嵌入python包的标准方法。我见过的大多数软件包都使用您的解决方案的某些变体,即eitner

  1. 嵌入版本,setup.pysetup.py生成version.py仅包含版本信息的模块(例如),该模块由您的软件包导入,或者

  2. 相反:将版本信息放入包本身,然后导入在其中设置版本 setup.py

There doesn’t seem to be a standard way to embed a version string in a python package. Most packages I’ve seen use some variant of your solution, i.e. eitner

  1. Embed the version in setup.py and have setup.py generate a module (e.g. version.py) containing only version info, that’s imported by your package, or

  2. The reverse: put the version info in your package itself, and import that to set the version in setup.py


回答 9

箭头以一种有趣的方式处理它。

现在(从2e5031b开始

arrow/__init__.py

__version__ = 'x.y.z'

setup.py

from arrow import __version__

setup(
    name='arrow',
    version=__version__,
    # [...]
)

之前

arrow/__init__.py

__version__ = 'x.y.z'
VERSION = __version__

setup.py

def grep(attrname):
    pattern = r"{0}\W*=\W*'([^']+)'".format(attrname)
    strval, = re.findall(pattern, file_text)
    return strval

file_text = read(fpath('arrow/__init__.py'))

setup(
    name='arrow',
    version=grep('__version__'),
    # [...]
)

arrow handles it in an interesting way.

Now (since 2e5031b)

In arrow/__init__.py:

__version__ = 'x.y.z'

In setup.py:

from arrow import __version__

setup(
    name='arrow',
    version=__version__,
    # [...]
)

Before

In arrow/__init__.py:

__version__ = 'x.y.z'
VERSION = __version__

In setup.py:

def grep(attrname):
    pattern = r"{0}\W*=\W*'([^']+)'".format(attrname)
    strval, = re.findall(pattern, file_text)
    return strval

file_text = read(fpath('arrow/__init__.py'))

setup(
    name='arrow',
    version=grep('__version__'),
    # [...]
)

回答 10

我还看到了另一种风格:

>>> django.VERSION
(1, 1, 0, 'final', 0)

I also saw another style:

>>> django.VERSION
(1, 1, 0, 'final', 0)

回答 11

使用setuptoolspbr

没有管理版本的标准方法,但是管理软件包的标准方法是setuptools

我发现总体上管理版本的最佳解决方案是setuptoolspbr扩展一起使用。现在,这是我管理版本的标准方法。

为完整项目设置项目对于简单项目可能是过大的,但是如果您需要管理版本,则可能处于正确的级别来设置所有内容。这样做还可以使您的软件包在PyPi上发布,因此每个人都可以通过Pip下载和使用它。

PBR将大多数元数据从setup.py工具中移出,并移到一个setup.cfg文件中,然后该文件用作大多数元数据的源,其中可以包括版本。这允许使用pyinstaller所需的类似方法将元数据打包到可执行文件中(如果需要,则可能需要此信息),并将元数据与其他程序包管理/设置脚本分开。您可以直接setup.cfg手动更新版本字符串,并且*.egg-info在构建软件包发行版时会将其拉入文件夹。然后,您的脚本可以使用各种方法从元数据访问版本(这些过程在下面的部分中概述)。

将Git用于VCS / SCM时,此设置甚至更好,因为它将从Git中提取很多元数据,这样您的回购就可以成为某些元数据的主要来源,包括版本,作者,变更日志,专门针对版本,它将基于存储库中的git标签为当前提交创建一个版本字符串。

由于PBR会直接从您的git repo中提取版本,作者,changelog和其他信息,因此setup.cfg每当为您的软件包创建发行版时(使用setup.py),其中的一些元数据就可以省去并自动生成

实时最新版本

setuptools将使用setup.py以下命令实时获取最新信息:

python setup.py --version

这将setup.cfg根据所做的最新提交和存储库中存在的标签,从文件或git存储库中提取最新版本。但是,此命令不会更新发行版中的版本。

更新版本

当您使用setup.pypy setup.py sdist例如)创建分发时,所有当前信息将被提取并存储在分发中。这实际上是运行setup.py --version命令,然后将该版本信息存储package.egg-info在存储分发元数据的一组文件中的文件夹中。

关于更新版本元数据的过程的注释:

如果您不使用pbr从git中提取版本数据,则只需使用新的版本信息直接更新setup.cfg(这很容易,但是请确保这是发布过程的标准部分)。

如果您使用的是git,而无需创建源代码或二进制发行版(使用python setup.py sdistpython setup.py bdist_xxx命令之一),则将git repo信息更新到<mypackage>.egg-info元数据文件夹中的最简单方法就是运行python setup.py install命令。这将运行与从git repo中提取元数据有关的所有PBR功能,并更新本地.egg-info文件夹,为已定义的任何入口点安装脚本可执行文件,以及运行此命令时从输出中看到的其他功能。

请注意,.egg-info通常不会将该文件夹存储在git repo本身的标准Python .gitignore文件中(例如,来自Gitignore.IO),因为可以从您的源中生成该文件夹。如果不包括在内,请确保您具有标准的“发布过程”以在发布之前在本地更新元数据,并且您上载到PyPi.org或以其他方式分发的任何软件包都必须包含此数据以具有正确的版本。如果您希望Git存储库包含此信息,则可以将特定文件排除在忽略范围之外(即添加!*.egg-info/PKG_INFO.gitignore

从脚本访问版本

您可以在包本身的Python脚本中从当前内部版本访问元数据。例如,对于版本,到目前为止,有几种方法可以实现:

## This one is a new built-in as of Python 3.8.0 should become the standard
from importlib-metadata import version

v0 = version("mypackage")
print('v0 {}'.format(v0))

## I don't like this one because the version method is hidden
import pkg_resources  # part of setuptools

v1 = pkg_resources.require("mypackage")[0].version
print('v1 {}'.format(v1))

# Probably best for pre v3.8.0 - the output without .version is just a longer string with
# both the package name, a space, and the version string
import pkg_resources  # part of setuptools

v2 = pkg_resources.get_distribution('mypackage').version
print('v2 {}'.format(v2))

## This one seems to be slower, and with pyinstaller makes the exe a lot bigger
from pbr.version import VersionInfo

v3 = VersionInfo('mypackage').release_string()
print('v3 {}'.format(v3))

您可以将其中之一直接放入__init__.py包中以提取版本信息,如下所示,类似于其他答案:

__all__ = (
    '__version__',
    'my_package_name'
)

import pkg_resources  # part of setuptools

__version__ = pkg_resources.get_distribution("mypackage").version

Using setuptools and pbr

There is not a standard way to manage version, but the standard way to manage your packages is setuptools.

The best solution I’ve found overall for managing version is to use setuptools with the pbr extension. This is now my standard way of managing version.

Setting up your project for full packaging may be overkill for simple projects, but if you need to manage version, you are probably at the right level to just set everything up. Doing so also makes your package releasable at PyPi so everyone can download and use it with Pip.

PBR moves most metadata out of the setup.py tools and into a setup.cfg file that is then used as a source for most metadata, which can include version. This allows the metadata to be packaged into an executable using something like pyinstaller if needed (if so, you will probably need this info), and separates the metadata from the other package management/setup scripts. You can directly update the version string in setup.cfg manually, and it will be pulled into the *.egg-info folder when building your package releases. Your scripts can then access the version from the metadata using various methods (these processes are outlined in sections below).

When using Git for VCS/SCM, this setup is even better, as it will pull in a lot of the metadata from Git so that your repo can be your primary source of truth for some of the metadata, including version, authors, changelogs, etc. For version specifically, it will create a version string for the current commit based on git tags in the repo.

As PBR will pull version, author, changelog and other info directly from your git repo, so some of the metadata in setup.cfg can be left out and auto generated whenever a distribution is created for your package (using setup.py)



Get the current version in real-time

setuptools will pull the latest info in real-time using setup.py:

python setup.py --version

This will pull the latest version either from the setup.cfg file, or from the git repo, based on the latest commit that was made and tags that exist in the repo. This command doesn’t update the version in a distribution though.



Updating the version metadata

When you create a distribution with setup.py (i.e. py setup.py sdist, for example), then all the current info will be extracted and stored in the distribution. This essentially runs the setup.py --version command and then stores that version info into the package.egg-info folder in a set of files that store distribution metadata.

Note on process to update version meta-data:

If you are not using pbr to pull version data from git, then just update your setup.cfg directly with new version info (easy enough, but make sure this is a standard part of your release process).

If you are using git, and you don’t need to create a source or binary distribution (using python setup.py sdist or one of the python setup.py bdist_xxx commands) the simplest way to update the git repo info into your <mypackage>.egg-info metadata folder is to just run the python setup.py install command. This will run all the PBR functions related to pulling metadata from the git repo and update your local .egg-info folder, install script executables for any entry-points you have defined, and other functions you can see from the output when you run this command.

Note that the .egg-info folder is generally excluded from being stored in the git repo itself in standard Python .gitignore files (such as from Gitignore.IO), as it can be generated from your source. If it is excluded, make sure you have a standard “release process” to get the metadata updated locally before release, and any package you upload to PyPi.org or otherwise distribute must include this data to have the correct version. If you want the Git repo to contain this info, you can exclude specific files from being ignored (i.e. add !*.egg-info/PKG_INFO to .gitignore)



Accessing the version from a script

You can access the metadata from the current build within Python scripts in the package itself. For version, for example, there are several ways to do this I have found so far:

## This one is a new built-in as of Python 3.8.0 should become the standard
from importlib-metadata import version

v0 = version("mypackage")
print('v0 {}'.format(v0))

## I don't like this one because the version method is hidden
import pkg_resources  # part of setuptools

v1 = pkg_resources.require("mypackage")[0].version
print('v1 {}'.format(v1))

# Probably best for pre v3.8.0 - the output without .version is just a longer string with
# both the package name, a space, and the version string
import pkg_resources  # part of setuptools

v2 = pkg_resources.get_distribution('mypackage').version
print('v2 {}'.format(v2))

## This one seems to be slower, and with pyinstaller makes the exe a lot bigger
from pbr.version import VersionInfo

v3 = VersionInfo('mypackage').release_string()
print('v3 {}'.format(v3))

You can put one of these directly in your __init__.py for the package to extract the version info as follows, similar to some other answers:

__all__ = (
    '__version__',
    'my_package_name'
)

import pkg_resources  # part of setuptools

__version__ = pkg_resources.get_distribution("mypackage").version

回答 12

在尝试寻找最简单可靠的解决方案几个小时后,以下是这些部分:

在包“ / mypackage”的文件夹内创建一个version.py文件:

# Store the version here so:
# 1) we don't load dependencies by storing it in __init__.py
# 2) we can import it in setup.py for the same reason
# 3) we can import it into your module module
__version__ = '1.2.7'

在setup.py中:

exec(open('mypackage/version.py').read())
setup(
    name='mypackage',
    version=__version__,

在主文件夹init .py中:

from .version import __version__

exec()函数在任何导入之外运行脚本,因为setup.py是在导入模块之前运行的。您仍然只需要在一个位置管理一个文件中的版本号,但是不幸的是,它不在setup.py中。(这是不利因素,但没有导入错误是有利因素)

After several hours of trying to find the simplest reliable solution, here are the parts:

create a version.py file INSIDE the folder of your package “/mypackage”:

# Store the version here so:
# 1) we don't load dependencies by storing it in __init__.py
# 2) we can import it in setup.py for the same reason
# 3) we can import it into your module module
__version__ = '1.2.7'

in setup.py:

exec(open('mypackage/version.py').read())
setup(
    name='mypackage',
    version=__version__,

in the main folder init.py:

from .version import __version__

The exec() function runs the script outside of any imports, since setup.py is run before the module can be imported. You still only need to manage the version number in one file in one place, but unfortunately it is not in setup.py. (that’s the downside, but having no import bugs is the upside)


回答 13

自首次提出这个问题以来,已完成了大量的工作,以统一版本和支持约定。现在,《Python打包用户指南》中详细介绍了可口的选项。同样值得注意的是,按照PEP 440版本号方案在Python中相对严格,因此,要使程序包发布到Cheese Shop,保持良好状态就至关重要。

以下是版本控制选项的简化分类:

  1. setup.pysetuptools)中读取文件并获取版本。
  2. 使用外部构建工具(同时更新__init__.py和源代码控制),例如bump2versionchangeszest.releaser
  3. 将值设置__version__为特定模块中的全局变量。
  4. 将值放在简单的VERSION文本文件中,以便setup.py和代码读取。
  5. 通过setup.py发行版设置值,并使用importlib.metadata在运行时将其提取。(警告,有3.8之前和3.8之后的版本。)
  6. 将值设置为__version__in sample/__init__.py并在中导入样本setup.py
  7. 使用setuptools_scm从源代码管理中提取版本控制,以便它是规范参考,而不是代码。

注意,(7)可能是最现代的方法(构建元数据与代码无关,由自动化发布)。另外请注意,如果安装程序用于软件包发行,则简单程序python3 setup.py --version将直接报告版本。

Lots of work toward uniform versioning and in support of conventions has been completed since this question was first asked. Palatable options are now detailed in the Python Packaging User Guide. Also noteworthy is that version number schemes are relatively strict in Python per PEP 440, and so keeping things sane is critical if your package will be released to the Cheese Shop.

Here’s a shortened breakdown of versioning options:

  1. Read the file in setup.py (setuptools) and get the version.
  2. Use an external build tool (to update both __init__.py as well as source control), e.g. bump2version, changes or zest.releaser.
  3. Set the value to a __version__ global variable in a specific module.
  4. Place the value in a simple VERSION text file for both setup.py and code to read.
  5. Set the value via a setup.py release, and use importlib.metadata to pick it up at runtime. (Warning, there are pre-3.8 and post-3.8 versions.)
  6. Set the value to __version__ in sample/__init__.py and import sample in setup.py.
  7. Use setuptools_scm to extract versioning from source control so that it’s the canonical reference, not code.

NOTE that (7) might be the most modern approach (build metadata is independent of code, published by automation). Also NOTE that if setup is used for package release that a simple python3 setup.py --version will report the version directly.


回答 14

值得一说的是,如果您使用的是NumPy distutils,numpy.distutils.misc_util.Configuration则可以使用make_svn_version_py()一种将修订版号嵌入package.__svn_version__变量中的方法version

For what it’s worth, if you’re using NumPy distutils, numpy.distutils.misc_util.Configuration has a make_svn_version_py() method that embeds the revision number inside package.__svn_version__ in the variable version .


回答 15

  1. 使用一个version.py文件只用__version__ = <VERSION>该文件在参数。在setup.py文件中导入__version__参数,然后将其值放在setup.py文件中,如下所示: version=__version__
  2. 另一种方法是仅使用setup.py带有version=<CURRENT_VERSION>-的文件CURRENT_VERSION是硬编码的。

由于我们不想每次创建新标签(准备发布新的软件包版本)时都手动更改文件中的版本,因此可以使用以下内容。

我强烈建议使用bumpversion程序包。多年来,我一直在使用它来改进版本。

首先添加version=<VERSION>setup.py文件(如果尚未添加)。

每次更改版本时,都应使用如下简短脚本:

bumpversion (patch|minor|major) - choose only one option
git push
git push --tags

然后为每个仓库添加一个文件.bumpversion.cfg

[bumpversion]
current_version = <CURRENT_TAG>
commit = True
tag = True
tag_name = {new_version}
[bumpversion:file:<RELATIVE_PATH_TO_SETUP_FILE>]

注意:

  • 您可以像其他帖子中所建议的那样__version__version.py文件下使用参数,并像这样更新bumpversion文件: [bumpversion:file:<RELATIVE_PATH_TO_VERSION_FILE>]
  • 必须 git commitgit reset您的回购中的所有内容,否则您将收到肮脏的回购错误。
  • 确保您的虚拟环境中包含了bumpversion程序包,如果没有,它将无法正常工作。
  1. Use a version.py file only with __version__ = <VERSION> param in the file. In the setup.py file import the __version__ param and put it’s value in the setup.py file like this: version=__version__
  2. Another way is to use just a setup.py file with version=<CURRENT_VERSION> – the CURRENT_VERSION is hardcoded.

Since we don’t want to manually change the version in the file every time we create a new tag (ready to release a new package version), we can use the following..

I highly recommend bumpversion package. I’ve been using it for years to bump a version.

start by adding version=<VERSION> to your setup.py file if you don’t have it already.

You should use a short script like this every time you bump a version:

bumpversion (patch|minor|major) - choose only one option
git push
git push --tags

Then add one file per repo called: .bumpversion.cfg:

[bumpversion]
current_version = <CURRENT_TAG>
commit = True
tag = True
tag_name = {new_version}
[bumpversion:file:<RELATIVE_PATH_TO_SETUP_FILE>]

Note:

  • You can use __version__ parameter under version.py file like it was suggested in other posts and update the bumpversion file like this: [bumpversion:file:<RELATIVE_PATH_TO_VERSION_FILE>]
  • You must git commit or git reset everything in your repo, otherwise you’ll get a dirty repo error.
  • Make sure that your virtual environment includes the package of bumpversion, without it it will not work.

回答 16

如果使用CVS(或RCS)并需要快速解决方案,则可以使用:

__version__ = "$Revision: 1.1 $"[11:-2]
__version_info__ = tuple([int(s) for s in __version__.split(".")])

(当然,修订号将由CVS代替。)

这为您提供了易于打印的版本和版本信息,可用于检查要导入的模块至少具有预期的版本:

import my_module
assert my_module.__version_info__ >= (1, 1)

If you use CVS (or RCS) and want a quick solution, you can use:

__version__ = "$Revision: 1.1 $"[11:-2]
__version_info__ = tuple([int(s) for s in __version__.split(".")])

(Of course, the revision number will be substituted for you by CVS.)

This gives you a print-friendly version and a version info that you can use to check that the module you are importing has at least the expected version:

import my_module
assert my_module.__version_info__ >= (1, 1)

相对导入超出顶级包错误

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

似乎这里已经有很多关于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.


“ pip install unroll”:“ python setup.py egg_info”失败,错误代码为1

问题:“ pip install unroll”:“ python setup.py egg_info”失败,错误代码为1

我是Python的新手,并一直在尝试使用安装某些软件包pip

但是pip install unroll给我

命令“ python setup.py egg_info”在C:\ Users \ MARKAN〜1 \ AppData \ Local \ Temp \ pip-build-wa7uco0k \ unroll \中失败,错误代码为1

我该如何解决?

I’m new to Python and have been trying to install some packages with pip.

But pip install unroll gives me

Command “python setup.py egg_info” failed with error code 1 in C:\Users\MARKAN~1\AppData\Local\Temp\pip-build-wa7uco0k\unroll\

How can I solve this?


回答 0

关于错误代码

根据Python文档

该模块提供了可用的标准errno系统符号。每个符号的值是相应的整数值。名称和描述是从linux / include / errno.h借来的,应该十分全面。

错误代码1在errno.h和中定义Operation not permitted

关于您的错误

您的setuptools似乎未安装。只需遵循Installation InstructionsPyPI网站上的即可。

如果已经安装,请尝试

pip install --upgrade setuptools

如果已经更新,请检查模块ez_setup是否缺失。如果是的话

pip install ez_setup

然后再试一次

pip install unroll

如果仍然无法正常运行,则可能是pip没有正确安装/升级setup_tools,因此您可能需要尝试

easy_install -U setuptools

然后再次

pip install unroll

About the error code

According to the Python documentation:

This module makes available standard errno system symbols. The value of each symbol is the corresponding integer value. The names and descriptions are borrowed from linux/include/errno.h, which should be pretty all-inclusive.

Error code 1 is defined in errno.h and means Operation not permitted.

About your error

Your setuptools do not appear to be installed. Just follow the Installation Instructions from the PyPI website.

If it’s already installed, try

pip install --upgrade setuptools

If it’s already up to date, check that the module ez_setup is not missing. If it is, then

pip install ez_setup

Then try again

pip install unroll

If it’s still not working, maybe pip didn’t install/upgrade setup_tools properly so you might want to try

easy_install -U setuptools

And again

pip install unroll

回答 1

这是一些指南,解释了我通常如何在Python + Windows上安装新软件包。看来您使用的是Windows路径,因此此答案将遵循特定的SO:

  • 我从不使用系统范围的Python安装。我只使用virtualenvs,通常我会尝试使用最新版本的2.x和3.x。
  • 我的第一次尝试总是pip install package_i_want在某些Visual Studio命令提示符下进行。什么Visual Studio命令提示符?好吧,理想情况下是与用来构建Python的Visual Studio相匹配的Visual Studio。例如,假设您的Python安装提示Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec 5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)] on win32。可以在此处找到用于编译Python的Visual Studio版本,因此v1500表示我将使用vs2008 x64命令提示符
  • 如果上一步由于某种原因而失败,我只是尝试使用 easy_install package_i_want
  • 如果上一步由于某种原因失败,我将转到gohlke网站,并检查我的包裹是否在那儿。如果是这样,我很幸运,我将其下载到virtualenv中,然后使用命令提示符转到该位置,然后执行pip install package_i_want.whl
  • 如果上一步没有成功,我将尝试自己制作轮子,一旦生成,我将尝试使用 pip install package_i_want.whl

现在,如果我们专注于您的特定问题,那么您将很难安装展开软件包。似乎最快的安装方式是执行以下操作:

  • git clone https://github.com/Zulko/unroll
  • cd unroll && python setup.py bdist_wheel
  • 将创建的dist文件夹中生成的unroll-0.1.0-py2-none-any.whl文件复制到virtualenv中。
  • pip install unroll-0.1.0-py2-none-any.whl

这样,它将安装没有任何问题。要检查它是否确实有效,只需登录Python安装并尝试import unroll,不要抱怨。

最后一点:这种方法几乎在99%的时间内都有效,有时您会发现一些特定于Unix或Mac OS X的pip程序包,在这种情况下,恐怕最好的方法是Windows版本正在向主要开发人员发布一些问题,或者您可以通过自己移植到Windows来获得一些乐趣(如果不走运,通常需要几个小时):)

Here’s a little guide explaining a little bit how I usually install new packages on Python + Windows. It seems you’re using Windows paths, so this answer will stick to that particular SO:

  • I never use a system-wide Python installation. I only use virtualenvs, and usually I try to have the latest version of 2.x & 3.x.
  • My first attempt is always doing pip install package_i_want in some of my Visual Studio command prompts. What Visual Studio command prompt? Well, ideally the Visual Studio which matches the one which was used to build Python. For instance, let’s say your Python installation says Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec 5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)] on win32. The version of Visual Studio used to compile Python can be found here, so v1500 means I’d be using vs2008 x64 command prompt
  • If the previous step failed for some reason I just try using easy_install package_i_want
  • If the previous step failed for some reason I go to gohlke website and I check whether my package is available over there. If it’s so, I’m lucky, I just download it into my virtualenv and then I just go to that location using a command prompt and I do pip install package_i_want.whl
  • If the previous step didn’t succeed I’ll just try to build the wheel myself and once it’s generated I’ll try to install it with pip install package_i_want.whl

Now, if we focus in your specific problem, where you’re having a hard time installing the unroll package. It seems the fastest way to install it is doing something like this:

  • git clone https://github.com/Zulko/unroll
  • cd unroll && python setup.py bdist_wheel
  • Copy the generated unroll-0.1.0-py2-none-any.whl file from the created dist folder into your virtualenv.
  • pip install unroll-0.1.0-py2-none-any.whl

That way it will install without any problems. To check it really works, just login into the Python installation and try import unroll, it shouldn’t complain.

One last note: This method works almost 99% of the time, and sometimes you’ll find some pip packages which are specific to Unix or Mac OS X, in that case, when that happens I’m afraid the best way to get a Windows version is either posting some issues to the main developers or having some fun by yourself porting to Windows (typically a few hours if you’re not lucky) :)


回答 2

升级点数后已解决:

python -m pip install --upgrade pip
pip install "package-name"

It was resolved after upgrading pip:

python -m pip install --upgrade pip
pip install "package-name"

回答 3

我完全陷入了与相同的错误psycopg2。看来我在安装Python和相关软件包时跳过了几个步骤。

  1. sudo apt-get install python-dev libpq-dev
  2. 转到您的虚拟环境
  3. pip install psycopg2

(在您的情况下,您需要替换psycopg2遇到问题的软件包。)

它无缝地工作。

I got stuck exactly with the same error with psycopg2. It looks like I skipped a few steps while installing Python and related packages.

  1. sudo apt-get install python-dev libpq-dev
  2. Go to your virtual env
  3. pip install psycopg2

(In your case you need to replace psycopg2 with the package you have an issue with.)

It worked seamlessly.


回答 4

在安装我得到同样的错误mitmproxy使用pip3。下面的命令解决了这个问题:

pip3 install --upgrade setuptools

I got this same error while installing mitmproxy using pip3. The below command fixed this:

pip3 install --upgrade setuptools

回答 5

  • Microsoft Visual C++ Compiler for Python 2.7https://www.microsoft.com/zh-cn/download/details.aspx?id=44266下载并安装-此程序包包含为Python 2.7程序包生成二进制文件所需的编译器和系统标头集。
  • 在提升模式下打开命令提示符(以管理员身份运行)
  • 首先要做 pip install ez_setup
  • 然后做pip install unroll(它将开始安装numpy, music21, decorator, imageio, tqdm, moviepy, unroll)#请耐心等待music21安装

使用python 2.7.11 64位

  • Download and install the Microsoft Visual C++ Compiler for Python 2.7 from https://www.microsoft.com/en-in/download/details.aspx?id=44266 – this package contains the compiler and set of system headers necessary for producing binary wheels for Python 2.7 packages.
  • Open a command prompt in elevated mode (run as administrator)
  • Firstly do pip install ez_setup
  • Then do pip install unroll (It will start installing numpy, music21, decorator, imageio, tqdm, moviepy, unroll) # Please be patient for music21 installation

Python 2.7.11 64 bit used


回答 6

另一种方式:

sudo apt-get install python-psycopg2 python-mysqldb

Other way:

sudo apt-get install python-psycopg2 python-mysqldb

回答 7

我有同样的问题。

问题是

pyparsing 2.2已经安装好了,我requirements.txt正在尝试安装pyparsing 2.0.1,抛出此错误

上下文:我使用的是virtualenv,似乎2.2来自我的全局操作系统Python site-packages,但是即使带有--no-site-packages标志(默认为上一个virtualenv中的默认标志),2.2仍然存在。肯定是因为我从他们的网站安装了Python,并将Python库添加到了我的$PATH

也许一个pip install --ignore-installed会工作。

解决方案:因为我需要向前移动,我只是删除了pyparsing==2.0.1从我的requirements.txt

I had the same problem.

The problem was:

pyparsing 2.2 was already installed and my requirements.txt was trying to install pyparsing 2.0.1 which throw this error

Context: I was using virtualenv, and it seems the 2.2 came from my global OS Python site-packages, but even with --no-site-packages flag (now by default in last virtualenv) the 2.2 was still present. Surely because I installed Python from their website and it added Python libraries to my $PATH.

Maybe a pip install --ignore-installed would have worked.

Solution: as I needed to move forwards, I just removed the pyparsing==2.0.1 from my requirements.txt.


回答 8

尝试使用pip安装Python模块时遇到了相同的错误代码。@Hackndo指出文档指出了安全问题。

基于该答案,我的问题通过运行带有sudo前缀的pip install命令得以解决:

sudo pip install python-mpd2

I ran into the same error code when trying to install a Python module with pip. @Hackndo noted that the documentation indicate a security issue.

Based on that answer, my problem was solved by running the pip install command with sudo prefixed:

sudo pip install python-mpd2

回答 9

在安装“ Twisted”库时遇到了相同的问题,并通过在Ubuntu 16.04(Xenial Xerus)上运行以下命令解决了该问题:

sudo apt-get install python-setuptools python-dev build-essential

I had the same issue when installing the “Twisted” library and solved it by running the following command on Ubuntu 16.04 (Xenial Xerus):

sudo apt-get install python-setuptools python-dev build-essential

回答 10

我尝试了以上所有方法,但均未成功。然后,我将Python版本从2.7.10更新到2.7.13,它解决了我遇到的问题。

I tried all of the above with no success. I then updated my Python version from 2.7.10 to 2.7.13, and it resolved the problems that I was experiencing.


回答 11

这意味着pip中的某些软件包较旧或未正确安装。

  1. 尝试检查版本,然后升级pip。如果可行,请使用自动删除。

  2. 如果pip命令始终对任何命令显示错误或冻结,等等。

  3. 最好的解决方案是将其卸载或完全删除。

  4. 安装一个新的点,然后更新和升级您的系统。

  5. 我给出了在此处新鲜安装pip的解决方案-python:无法打开文件get-pip.py错误2]没有此类文件或目录

That means some packages in pip are old or not correctly installed.

  1. Try checking version and then upgrading pip.Use auto remove if that works.

  2. If the pip command shows an error all the time for any command or it freezes, etc.

  3. The best solution is to uninstall it or remove it completely.

  4. Install a fresh pip and then update and upgrade your system.

  5. I have given a solution to installing pip fresh here – python: can’t open file get-pip.py error 2] no such file or directory


回答 12

这对我来说是更简单的方法:

pip2 install Name

因此,如果您使用的是pip,请尝试使用pip3pip2

它应该解决问题。

This was the easier way for me:

pip2 install Name

So if you was using pip, try to use pip3 or pip2

It should solve the problem.


回答 13

pip3 install –upgrade setuptools警告:pip正在由旧的脚本包装程序调用。这将在以后的pip版本中失败。请参阅https://github.com/pypa/pip/issues/5599,以获取有关解决基本问题的建议。

******为了避免此问题,您可以使用-m pip调用Python,而不是直接运行pip。******

使用python3 -m pip“命令”例如:python3 -m pip install –user pyqt5

pip3 install –upgrade setuptools WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip. Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.

******To avoid this problem you can invoke Python with ‘-m pip’ instead of running pip directly.******

use python3 -m pip “command” eg: python3 -m pip install –user pyqt5


回答 14

这为我工作:

sudo xcodebuild -license

This worked for me:

sudo xcodebuild -license

回答 15

将Python升级到版本3解决了我的问题。什么都没做。

Upgrading Python to version 3 fixed my problem. Nothing else did.


回答 16

我从http://www.lfd.uci.edu/~gohlke/pythonlibs/下载了.whl文件,然后执行了以下操作:

pip install scipy-0.19.1-cp27-cp27m-win32.whl

请注意,您需要使用的版本(win32 / win_amd-64)取决于Python的版本,而不取决于Windows的版本。

I downloaded the .whl file from http://www.lfd.uci.edu/~gohlke/pythonlibs/ and then did:

pip install scipy-0.19.1-cp27-cp27m-win32.whl

Note that the version you need to use (win32/win_amd-64) depends on the version of Python and not that of Windows.


回答 17

我在新的开发设置上使用virtualenvs(带有pipenv)遇到了这个问题。

我只能通过将psycopg2版本从2.6.2升级到2.7.3来解决它。更多信息在https://github.com/psycopg/psycopg2/issues/594

I had this problem using virtualenvs (with pipenv) on my new development setup.

I could only solve it by upgrading the psycopg2 version from 2.6.2 to 2.7.3. More information is at https://github.com/psycopg/psycopg2/issues/594


回答 18

我在使用相同的错误消息时遇到了同样的问题,但是在Ubuntu 16.04 LTS(Xenial Xerus)上却相反:

命令“ python setup.py egg_info”在/ tmp / pip-install-w71uo1rg / poster /中失败,错误代码为1

我测试了上面提供的所有解决方案,但没有一个对我有用。我阅读了完整的TraceBack,发现我必须使用python版本2.7创建虚拟环境(默认情况下使用Python 3.5):

virtualenv --python=/usr/bin/python2.7 my_venv

激活它后,我将pip install unirest成功运行。

I faced the same problem with the same error message but on Ubuntu 16.04 LTS (Xenial Xerus) instead:

Command “python setup.py egg_info” failed with error code 1 in /tmp/pip-install-w71uo1rg/poster/

I tested all the solutions provided above and none of them worked for me. I read the full TraceBack and found out I had to create the virtual environment with Python version 2.7 instead (the default one uses Python 3.5 instead):

virtualenv --python=/usr/bin/python2.7 my_venv

Once I activated it, I run pip install unirest successfully.


回答 19

尝试在Linux上:

sudo apt install python-pip python-bluez libbluetooth-dev libboost-python-dev libboost-thread-dev libglib2.0-dev bluez bluez-hcidump

try on linux:

sudo apt install python-pip python-bluez libbluetooth-dev libboost-python-dev libboost-thread-dev libglib2.0-dev bluez bluez-hcidump

回答 20

我使用以下方法在Centos 7上解决了该问题:

sudo yum install libcurl-devel

I solved it on Centos 7 by using:

sudo yum install libcurl-devel

回答 21

我的Win10 PC上使用不同的软件包时遇到了相同的问题,并尝试了到目前为止提到的所有内容。

最后通过禁用Comodo Auto-Containment解决了该问题。

由于没有人提及它,我希望它能对某人有所帮助。

Had the same problem on my Win10 PC with different packages and tried everything mentioned so far.

Finally solved it by disabling Comodo Auto-Containment.

Since nobody has mentioned it yet, I hope it helps someone.


回答 22

我遇到了同样的问题,可以通过以下操作解决。

Windows Python需要通过SDK安装的Visual C ++库来构建代码,例如通过setuptools.extension.Extension或numpy.distutils.core.Extension。例如,在Windows中使用Python构建f2py模块需要安装上述Visual C ++ SDK。在Linux和Mac上,C ++库随编译器一起安装。

https://www.scivision.co/python-windows-visual-c++-14-required/

I had the same problem and was able to fix by doing the following.

Windows Python needs Visual C++ libraries installed via the SDK to build code, such as via setuptools.extension.Extension or numpy.distutils.core.Extension. For example, building f2py modules in Windows with Python requires Visual C++ SDK as installed above. On Linux and Mac, the C++ libraries are installed with the compiler.

https://www.scivision.co/python-windows-visual-c++-14-required/


回答 23

以下命令对我有用

[root@sandbox ~]# pip install google-api-python-client==1.6.4

Following below command worked for me

[root@sandbox ~]# pip install google-api-python-client==1.6.4

回答 24

更新setuptools时解决setup.pu egg_info问题的方法或其他方法不起作用。

  1. 如果CONDA可以安装版本的库,请使用conda而不是pip。
  2. 克隆库回购,然后尝试通过pip install -e .或通过进行安装python setup.py install

Methods to solve setup.pu egg_info issue when updating setuptools or not other methods doesnot works.

  1. If CONDA version of the library is available to install use conda instead of pip.
  2. Clone the library repo and then try installation by pip install -e . or by python setup.py install

Python模块和Python包之间有什么区别?

问题:Python模块和Python包之间有什么区别?

Python模块和Python包之间有什么区别?

另请参阅:“程序包”和“模块”之间有什么区别(对于其他语言)

What’s the difference between a Python module and a Python package?

See also: What’s the difference between “package” and “module” (for other languages)


回答 0

模块是在一个导入下导入并使用的单个文件。例如

import my_module

软件包是目录中提供软件包层次结构的模块的集合。

from my_package.timing.danger.internets import function_of_love

模块文档

套餐介绍

A module is a single file (or files) that are imported under one import and used. e.g.

import my_module

A package is a collection of modules in directories that give a package hierarchy.

from my_package.timing.danger.internets import function_of_love

Documentation for modules

Introduction to packages


回答 1

任何Python文件都是一个模块,其名称是文件的基础名称,不带.py扩展名。甲是Python模块的集合:而一个模块是一个Python文件,一个包是含有一个额外的Python模块的目录__init__.py文件中,一个包从恰好包含一堆Python脚本的一个目录区分开。包可以嵌套到任何深度,只要相应的目录包含它们自己的__init__.py文件即可。

模块和软件包之间的区别似乎仅在文件系统级别上存在。导入模块或包时,Python创建的相应对象始终为类型module。但是请注意,当您导入软件包时,仅__init__.py该软件包文件中的变量/函数/类是直接可见的,子软件包或模块则不可见。例如,考虑xmlPython标准库中的包:其xml目录包含一个__init__.py文件和四个子目录;子目录etree包含一个__init__.py文件,以及其他ElementTree.py文件。查看当您尝试以交互方式导入包/模块时会发生什么:

>>> import xml
>>> type(xml)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> import xml.etree
>>> type(xml.etree)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> import xml.etree.ElementTree
>>> type(xml.etree.ElementTree)
<type 'module'>
>>> xml.etree.ElementTree.parse
<function parse at 0x00B135B0>

在Python中,还有一些内置模块(例如)sys,这些模块都是用C语言编写的,但我认为您并不是要考虑问题中的那些模块。

Any Python file is a module, its name being the file’s base name without the .py extension. A package is a collection of Python modules: while a module is a single Python file, a package is a directory of Python modules containing an additional __init__.py file, to distinguish a package from a directory that just happens to contain a bunch of Python scripts. Packages can be nested to any depth, provided that the corresponding directories contain their own __init__.py file.

The distinction between module and package seems to hold just at the file system level. When you import a module or a package, the corresponding object created by Python is always of type module. Note, however, when you import a package, only variables/functions/classes in the __init__.py file of that package are directly visible, not sub-packages or modules. As an example, consider the xml package in the Python standard library: its xml directory contains an __init__.py file and four sub-directories; the sub-directory etree contains an __init__.py file and, among others, an ElementTree.py file. See what happens when you try to interactively import package/modules:

>>> import xml
>>> type(xml)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> import xml.etree
>>> type(xml.etree)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> import xml.etree.ElementTree
>>> type(xml.etree.ElementTree)
<type 'module'>
>>> xml.etree.ElementTree.parse
<function parse at 0x00B135B0>

In Python there also are built-in modules, such as sys, that are written in C, but I don’t think you meant to consider those in your question.


回答 2

Python词汇表中

重要的是要记住,所有软件包都是模块,但并非所有模块都是软件包。换句话说,包只是一种特殊的模块。具体来说,任何包含__path__属性的模块都被视为包。

名称中带有破折号的Python文件(如my-file.py)无法通过简单的import语句导入。代码明智的,import my-file是一样的import my - file,这将引发异常。这样的文件可以更好地描述为脚本,而可导入文件是模块

From the Python glossary:

It’s important to keep in mind that all packages are modules, but not all modules are packages. Or put another way, packages are just a special kind of module. Specifically, any module that contains a __path__ attribute is considered a package.

Python files with a dash in the name, like my-file.py, cannot be imported with a simple import statement. Code-wise, import my-file is the same as import my - file which will raise an exception. Such files are better characterized as scripts whereas importable files are modules.


回答 3

首先,请记住,按照其精确定义,模块是Python解释器内存中的对象,通常是通过从磁盘读取一个或多个文件来创建的。虽然我们可以非正式地称呼磁盘文件(例如a/b/c.py“模块”),但实际上它并没有与其他来自其他来源(例如sys.path)的信息组合在一起以创建模块对象,而是变成一个文件。

(例如,请注意,可以根据相同的sys.path设置和其他设置,从同一个文件中加载名称不同的两个模块。这正是在解释器中python -m my.module后面跟着的情况import my.module;将有两个模块对象,__main__并且my.module都创建了来自磁盘上的同一文件,my/module.py。)

是可以具有子模块(包括子包)的模块。并非所有模块都能做到这一点。例如,创建一个小的模块层次结构:

$ mkdir -p a/b
$ touch a/b/c.py

确保下没有其他文件a。启动Python 3.4或更高版本的解释器(例如,使用python3 -i)并检查以下语句的结果:

import a
a                 <module 'a' (namespace)>
a.b               AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b               <module 'a.b' (namespace)>
a.b.c             <module 'a.b.c' from '/home/cjs/a/b/c.py'>

模块aa.b是程序包(实际上,一种程序包称为“命名空间程序包”,尽管我们在这里不必担心)。但是,模块a.b.c不是包。我们可以通过a/b.py在上面的目录结构中添加另一个文件并启动一个新的解释器来演示这一点:

import a.b.c
 ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a                 <module 'a' (namespace)>
a.__path__        _NamespacePath(['/.../a'])
a.b               <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__      AttributeError: 'module' object has no attribute '__path__'

Python确保在加载子模块之前先加载所有父模块。在其上方找到a/一个目录,因此创建了一个命名空间包a,这a/b.py是一个Python源文件,它被加载并用于创建(非包)模块a.b。此时,您无法拥有模块,a.b.c因为a.b它不是软件包,因此不能拥有子模块。

您还可以在此处看到package模块a具有__path__属性(packages必须具有此属性),但非package模块a.b则没有。

First, keep in mind that, in its precise definition, a module is an object in the memory of a Python interpreter, often created by reading one or more files from disk. While we may informally call a disk file such as a/b/c.py a “module,” it doesn’t actually become one until it’s combined with information from several other sources (such as sys.path) to create the module object.

(Note, for example, that two modules with different names can be loaded from the same file, depending on sys.path and other settings. This is exactly what happens with python -m my.module followed by an import my.module in the interpreter; there will be two module objects, __main__ and my.module, both created from the same file on disk, my/module.py.)

A package is a module that may have submodules (including subpackages). Not all modules can do this. As an example, create a small module hierarchy:

$ mkdir -p a/b
$ touch a/b/c.py

Ensure that there are no other files under a. Start a Python 3.4 or later interpreter (e.g., with python3 -i) and examine the results of the following statements:

import a
a                ⇒ <module 'a' (namespace)>
a.b              ⇒ AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b              ⇒ <module 'a.b' (namespace)>
a.b.c            ⇒ <module 'a.b.c' from '/home/cjs/a/b/c.py'>

Modules a and a.b are packages (in fact, a certain kind of package called a “namespace package,” though we wont’ worry about that here). However, module a.b.c is not a package. We can demonstrate this by adding another file, a/b.py to the directory structure above and starting a fresh interpreter:

import a.b.c
⇒ ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a                ⇒ <module 'a' (namespace)>
a.__path__       ⇒ _NamespacePath(['/.../a'])
a.b              ⇒ <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__     ⇒ AttributeError: 'module' object has no attribute '__path__'

Python ensures that all parent modules are loaded before a child module is loaded. Above it finds that a/ is a directory, and so creates a namespace package a, and that a/b.py is a Python source file which it loads and uses to create a (non-package) module a.b. At this point you cannot have a module a.b.c because a.b is not a package, and thus cannot have submodules.

You can also see here that the package module a has a __path__ attribute (packages must have this) but the non-package module a.b does not.


回答 4

一个较晚的答案,还有另一个定义:

包由导入的顶级实体表示,该顶级实体可以是一个独立的模块,也可以是__init__.py特殊模块,它是子目录结构中一组模块中的顶级实体。

因此,从物理上说,包装就是一个分配单元,它提供一个或多个模块。

A late answer, yet another definition:

A package is represented by an imported top-entity which could either be a self-contained module, or the __init__.py special module as the top-entity from a set of modules within a sub directory structure.

So physically a package is a distribution unit, which provides one or more modules.


回答 5

包也是一个模块,可以包含其他模块,“基于文件的简单模块和包(子包)”。与模块的包装类型相关的代码进入该__init__.py文件。

import pack1
print(type(pack1))

而模块是一个简单的文件,可以包含函数,类,可运行代码等。导入模块后,它的行为就像一个对象,您可以通过该对象访问模块中定义的标识符。

The Package is also a module that can contain other modules, ‘simple file-based modules, and packages (sub-package)’. The code related to the package type of module goes into the __init__.py file.

import pack1
print(type(pack1))

whereas modules are a simple file that can contain functions, classes, runnable code, etc. after importing a module it behaves like an object by which you can access the identifiers defined in the module.


如何使用Python 3安装pip?

问题:如何使用Python 3安装pip?

我要安装pip。它应支持Python 3,但需要setuptools,该工具仅适用于Python 2。

如何使用Python 3安装pip?

I want to install pip. It should support Python 3, but it requires setuptools, which is available only for Python 2.

How can I install pip with Python 3?


回答 0

编辑:手动安装和使用setuptools不再是标准过程。

如果您运行的是Python 2.7.9+或Python 3.4+

恭喜,您应该已经pip安装了。如果您不这样做,请继续阅读。

如果您正在运行类似Unix的系统

pip如果您的Python版本低于2.7.9或3.4,或者您的系统出于任何原因未包含该软件包,通常可以通过软件包管理器进行安装。

以下是一些更常见发行版的说明。

在适用于Python 2.x的Debian(Wheezy和更高版本)和Ubuntu(Trusty Tahr和更高版本)上安装

从终端运行以下命令:

sudo apt-get install python-pip 

在适用于Python 3.x的Debian(Wheezy和更高版本)和Ubuntu(Trusty Tahr和更高版本)上安装

从终端运行以下命令:

sudo apt-get install python3-pip
注意:

在全新安装的Debian / Ubuntu中,只有在执行以下操作后才能找到该软件包:

sudo apt-get update

pip在适用于Python 2.x的CentOS 7上安装

在CentOS 7上,您必须先安装设置工具,然后再使用它来安装pip,因为它没有直接的软件包。

sudo yum install python-setuptools
sudo easy_install pip

pip在适用于Python 3.x的CentOS 7上安装

假设您从EPEL安装了Python 3.4 ,则可以安装Python 3的设置工具并使用它进行安装pip

# First command requires you to have enabled EPEL for CentOS7
sudo yum install python34-setuptools
sudo easy_install pip

如果您的Unix / Linux发行版未在软件包repos中包含它

使用下面详细介绍的手动方法进行安装。

手动方式

如果您想手动进行操作,现在推荐的方法是使用安装说明中get-pip.py脚本进行pip安装

安装点子

要安装pip,请安全下载 get-pip.py

然后运行以下命令(可能需要管理员访问权限):

python get-pip.py 

如果setuptools尚未安装,get-pip.py将为您安装setuptools。

edit: Manual installation and use of setuptools is not the standard process anymore.

If you’re running Python 2.7.9+ or Python 3.4+

Congrats, you should already have pip installed. If you do not, read onward.

If you’re running a Unix-like System

You can usually install the package for pip through your package manager if your version of Python is older than 2.7.9 or 3.4, or if your system did not include it for whatever reason.

Instructions for some of the more common distros follow.

Installing on Debian (Wheezy and newer) and Ubuntu (Trusty Tahr and newer) for Python 2.x

Run the following command from a terminal:

sudo apt-get install python-pip 

Installing on Debian (Wheezy and newer) and Ubuntu (Trusty Tahr and newer) for Python 3.x

Run the following command from a terminal:

sudo apt-get install python3-pip
Note:

On a fresh Debian/Ubuntu install, the package may not be found until you do:

sudo apt-get update

Installing pip on CentOS 7 for Python 2.x

On CentOS 7, you have to install setup tools first, and then use that to install pip, as there is no direct package for it.

sudo yum install python-setuptools
sudo easy_install pip

Installing pip on CentOS 7 for Python 3.x

Assuming you installed Python 3.4 from EPEL, you can install Python 3’s setup tools and use it to install pip.

# First command requires you to have enabled EPEL for CentOS7
sudo yum install python34-setuptools
sudo easy_install pip

If your Unix/Linux distro doesn’t have it in package repos

Install using the manual way detailed below.

The manual way

If you want to do it the manual way, the now-recommended method is to install using the get-pip.py script from pip‘s installation instructions.

Install pip

To install pip, securely download get-pip.py

Then run the following (which may require administrator access):

python get-pip.py 

If setuptools is not already installed, get-pip.py will install setuptools for you.


回答 1

我可以通过运行Ubuntu在python 3上安装pip sudo apt-get install python3-pip

I was able to install pip for python 3 on Ubuntu just by running sudo apt-get install python3-pip.


回答 2

Python 3.4以上和Python 2.7.9以上

好消息!Pip随附了Python 3.4(2014年3月发布)。这是所有Python版本中的最佳功能。它使每个人都可以访问社区丰富的图书馆。新手不再因安装的困难而被排除在外。在与软件包管理器一起交付时,Python加入了Ruby,Nodejs,Haskell,Perl,Go以及几乎所有其他具有主流开源社区的当代语言。谢谢Python。

当然,这并不意味着Python打包已解决问题。经验仍然令人沮丧。我在Python是否有软件包/模块管理系统中讨论了这一点

las惜使用早期Python的每个人。遵循手册说明。

Python≤2.7.8和Python≤3.3

按照我的详细说明在 https://stackoverflow.com/a/12476379/284795。实质上

官方指示

根据https://pip.pypa.io/en/stable/installing.html

下载时get-pip.py,请小心保存为.py文件而不是文件.txt。然后,在命令提示符下运行它。

python get-pip.py

您可能需要管理员命令提示符才能执行此操作。遵循http://technet.microsoft.com/en-us/library/cc947813(v=ws.10).aspx

对我来说,此安装点位于C:\Python27\Scripts\pip.exepip.exe在您的计算机上查找,然后将其文件夹(例如C:\Python27\Scripts)添加 到您的路径(开始/编辑环境变量)。现在,您应该可以从命令行运行pip了。尝试安装软件包:

pip install httpie

你去了(希望)!

Python 3.4+ and Python 2.7.9+

Good news! Python 3.4 (released March 2014) ships with Pip. This is the best feature of any Python release. It makes the community’s wealth of libraries accessible to everyone. Newbies are no longer excluded by the prohibitive difficulty of setup. In shipping with a package manager, Python joins Ruby, Nodejs, Haskell, Perl, Go–almost every other contemporary language with a majority open-source community. Thank you Python.

Of course, that doesn’t mean Python packaging is problem solved. The experience remains frustrating. I discuss this at Does Python have a package/module management system?

Alas for everyone using an earlier Python. Manual instructions follow.

Python ≤ 2.7.8 and Python ≤ 3.3

Follow my detailed instructions at https://stackoverflow.com/a/12476379/284795 . Essentially

Official instructions

Per https://pip.pypa.io/en/stable/installing.html

Download get-pip.py, being careful to save it as a .py file rather than .txt. Then, run it from the command prompt.

python get-pip.py

You possibly need an administrator command prompt to do this. Follow http://technet.microsoft.com/en-us/library/cc947813(v=ws.10).aspx

For me, this installed Pip at C:\Python27\Scripts\pip.exe. Find pip.exe on your computer, then add its folder (eg. C:\Python27\Scripts) to your path (Start / Edit environment variables). Now you should be able to run pip from the command line. Try installing a package:

pip install httpie

There you go (hopefully)!


回答 3

对于Ubuntu 12.04或更旧版本,

sudo apt-get install python3-pip

将无法正常工作。而是使用:

sudo apt-get install python3-setuptools ca-certificates
sudo easy_install3 pip

For Ubuntu 12.04 or older,

sudo apt-get install python3-pip

won’t work. Instead, use:

sudo apt-get install python3-setuptools ca-certificates
sudo easy_install3 pip

回答 4

如果您使用的是python 3.4+

只需输入:

python3 -m pip

if you’re using python 3.4+

just type:

python3 -m pip

回答 5

2015年1月20日更新:

根据https://pip.pypa.io/en/latest/installing.html,当前方式为:

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

我认为这适用于任何版本


原始答案:

wget http://python-distribute.org/distribute_setup.py
python distribute_setup.py
easy_install pip

Update 2015-01-20:

As per https://pip.pypa.io/en/latest/installing.html the current way is:

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

I think that should work for any version


Original Answer:

wget http://python-distribute.org/distribute_setup.py
python distribute_setup.py
easy_install pip

回答 6

系统中的单个Python

要在Python中安装软件包,请始终遵循以下步骤:

  1. 如果包装是用于python 2.xsudo python -m pip install [package]
  2. 如果包装是用于python 3.xsudo python3 -m pip install [package]

注意:这是假设未为设置别名 python

通过这种方法,将不会混淆哪个Python版本正在接收该软件包。

多个Python

假设你有python3 ↔ python3.6python3.7 ↔ python3.7

  1. 要安装python3.6sudo python3 -m pip install [package]
  2. 要安装python3.7sudo python3.7 -m pip install [package]

这基本上与前面显示的方法相同。

注1

如何找到您的python3命令产生的python :

ganesh@Ganesh:~$ python3 # Type in terminal
Python 3.6.6 (default, Sep 12 2018, 18:26:19) # Your python3 version
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

注意第二行中的python 3.6.6

笔记2

更改python3python指向以下内容:https : //askubuntu.com/questions/320996/how-to-make-python-program-command-execute-python-3

Single Python in system

To install packages in Python always follow these steps:

  1. If the package is for python 2.x: sudo python -m pip install [package]
  2. If the package is for python 3.x: sudo python3 -m pip install [package]

Note: This is assuming no alias is set for python

Through this method, there will be no confusion regarding which python version is receiving the package.

Multiple Pythons

Say you have python3 ↔ python3.6 and python3.7 ↔ python3.7

  1. To install for python3.6: sudo python3 -m pip install [package]
  2. To instal for python3.7: sudo python3.7 -m pip install [package]

This is essentially the same method as shown previously.

Note 1

How to find which python, your python3 command spawns:

ganesh@Ganesh:~$ python3 # Type in terminal
Python 3.6.6 (default, Sep 12 2018, 18:26:19) # Your python3 version
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Notice python 3.6.6 in the second line.

Note 2

Change what python3 or python points to: https://askubuntu.com/questions/320996/how-to-make-python-program-command-execute-python-3


回答 7

python3 -m ensurepip

我不确定何时确切引入此功能,但尚不存在时会为我安装pip3。

python3 -m ensurepip

I’m not sure when exactly this was introduced, but it’s installed pip3 for me when it didn’t already exist.


回答 8

旧版的Homebrew

如果您使用的是macOS,请使用homebrew

brew install python3 # this installs python only
brew postinstall python3 # this command installs pip

另请注意,如果安装成功完成,则应检查控制台。有时没有(例如由于所有权引起的错误),但是人们只是忽略了日志。


更新-1.5之后的自制软件版本

根据官方的Homebrew页面

在2018年3月1日,python公式将升级到Python 3.x,并且将添加python @ 2公式以安装Python 2.7(尽管这仅是小桶,因此默认情况下,不将python和python2添加到PATH中,而无需手动冲泡链接–force)。我们将维护python2,python3和python @ 3别名。

因此,要安装Python 3,请运行以下命令:

brew install python3

然后,pip会自动安装,您可以通过来安装任何软件包pip install <package>

Older version of Homebrew

If you are on macOS, use homebrew.

brew install python3 # this installs python only
brew postinstall python3 # this command installs pip

Also note that you should check the console if the install finished successfully. Sometimes it doesn’t (e.g. an error due to ownership), but people simply overlook the log.


UPDATED – Homebrew version after 1.5

According to the official Homebrew page:

On 1st March 2018 the python formula will be upgraded to Python 3.x and a python@2 formula will be added for installing Python 2.7 (although this will be keg-only so neither python nor python2 will be added to the PATH by default without a manual brew link –force). We will maintain python2, python3 and python@3 aliases.

So to install Python 3, run the following command:

brew install python3

Then, the pip is installed automatically, and you can install any package by pip install <package>.


回答 9

如果您使用多个不同版本的python,请尝试使用virtualenv http://www.virtualenv.org/en/latest/virtualenv.html#installation

具有pip针对每个本地环境的优势。

然后通过以下方式在当前目录中安装本地环境:

virtualenv -p /usr/local/bin/python3.3 ENV --verbose

请注意,您指定了系统上已安装的python二进制文件的路径。

然后在该文件夹中有一个本地pythonenvironment。 ./ENV

现在应该有 ./ENV/pip-3.3

用于 ./ENV/pip-3.3 freeze列出本地安装的库。

用于./ENV/pip-3.3 install packagename在本地环境中安装。

用于./ENV/python3.3 pythonfile.py运行您的python脚本。

If you use several different versions of python try using virtualenv http://www.virtualenv.org/en/latest/virtualenv.html#installation

With the advantage of pip for each local environment.

Then install a local environment in the current directory by:

virtualenv -p /usr/local/bin/python3.3 ENV --verbose

Note that you specify the path to a python binary you have installed on your system.

Then there are now an local pythonenvironment in that folder. ./ENV

Now there should be ./ENV/pip-3.3

use ./ENV/pip-3.3 freeze to list the local installed libraries.

use ./ENV/pip-3.3 install packagename to install at the local environment.

use ./ENV/python3.3 pythonfile.py to run your python script.


回答 10

这是我在ubuntu 12.04上解决此问题的方法:

sudo apt-get install build-essential libncursesw5-dev libssl-dev libgdbm-dev libc6-dev libsqlite3-dev tk-dev

然后从源代码安装python3:

wget https://www.python.org/ftp/python/3.4.0/Python-3.4.0.tar.xz
tar xvf Python-3.4.0.tar.xz
cd Python-3.4.0
./configure
make
make test
sudo make install

当您全部安装完后,pip3将自动安装。

Here is my way to solve this problem at ubuntu 12.04:

sudo apt-get install build-essential libncursesw5-dev libssl-dev libgdbm-dev libc6-dev libsqlite3-dev tk-dev

Then install the python3 from source code:

wget https://www.python.org/ftp/python/3.4.0/Python-3.4.0.tar.xz
tar xvf Python-3.4.0.tar.xz
cd Python-3.4.0
./configure
make
make test
sudo make install

When you finished installing all of them, pip3 will get installed automatically.


回答 11

这就是我在OS X Mavericks上所做的工作,以使其正常工作。

首先,冲泡安装了

安装python 3.4

brew install python3

然后,我得到了最新版本的distribution:

wget https://pypi.python.org/packages/source/d/distribute/distribute-0.7.3.zip#md5=c6c59594a7b180af57af8a0cc0cf5b4a

unzip distribute-0.7.3.zip
cd distribute-0.7.3
sudo setup.py install
sudo easy_install-3.4 pip
sudo pip3.4 install virtualenv
sudo pip3.4 install virtualenvwrapper

mkvirtualenv py3 

python --version
Python 3.4.1

我希望这有帮助。

This is what I did on OS X Mavericks to get this to work.

Firstly, have brew installed

Install python 3.4

brew install python3

Then I get the latest version of distribute:

wget https://pypi.python.org/packages/source/d/distribute/distribute-0.7.3.zip#md5=c6c59594a7b180af57af8a0cc0cf5b4a

unzip distribute-0.7.3.zip
cd distribute-0.7.3
sudo setup.py install
sudo easy_install-3.4 pip
sudo pip3.4 install virtualenv
sudo pip3.4 install virtualenvwrapper

mkvirtualenv py3 

python --version
Python 3.4.1

I hope this helps.


回答 12

Python 3.4新增功能

点子应该总是可用

默认情况下,命令pipX和pipX.Y将连同pip Python软件包及其依赖项一起安装在所有平台上(其中XY代表Python安装的版本)。

https://docs.python.org/3/whatsnew/3.4.html#whatsnew-pep-453

因此,如果您安装了python 3.4,则可以: sudo pip3 install xxx

What’s New In Python 3.4

pip should always be available

By default, the commands pipX and pipX.Y will be installed on all platforms (where X.Y stands for the version of the Python installation), along with the pip Python package and its dependencies.

https://docs.python.org/3/whatsnew/3.4.html#whatsnew-pep-453

so if you have python 3.4 installed, you can just: sudo pip3 install xxx


回答 13

对于python3,请尝试以下操作:

wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python

好消息是它还将检测您拥有的python版本(即使它是您自定义位置中的python环境)。之后,您可以正常进行操作(例如)

pip install numpy

资源: https //pypi.python.org/pypi/setuptools/1.1.6#upgrading-from-setuptools-0-6

For python3 try this:

wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python

The good thing is that It will also detect what version of python you have (even if it’s an environment of python in your custom location). After this you can proceed normally with (for example)

pip install numpy

source: https://pypi.python.org/pypi/setuptools/1.1.6#upgrading-from-setuptools-0-6


回答 14

假设您处于高度受限的计算机环境中(例如我本人),而没有root访问权限或无法安装软件包…

在发布本文之前,我从未设置过Python / virtualenv的新/独立/原始/非根实例。我已经做了很多谷歌搜索工作。

  1. 确定您使用的是python(python2)还是python3,并正确设置PATH。(我严格是python3用户。)如果您是python2用户python3python则下面的所有命令都可以代替。
  2. wget https://pypi.python.org/packages/source/v/virtualenv/virtualenv-x.y.z.tar.gz
  3. tar -xzvf virtualenv-x.y.z.tar.gz
  4. python3 virtualenv-x.y.z/virtualenv.py --python $(which python3) /path/to/new/virtualenv
  5. source /path/to/new/virtualenv/bin/activate
    • 假设您使用的是兼容Bourne的外壳,例如bash
    • 出色的是,此virtualenv软件包包括的独立版本,pip并且setuptools会自动神奇地安装到每个新的virtualenv中。这解决了鸡肉和鸡蛋的问题。
    • 您可能想为此最终命令创建一个别名(或更新〜/ .bashrc等),以在每次登录时激活python virtualenv。记住所有这些路径和命令可能很痛苦。
  6. 现在检查您的python版本:which python3应该给出:/path/to/new/virtualenv/bin/python3
  7. pip也可以通过以下命令在virtualenv中进行检查which pip:应该给出:/path/to/new/virtualenv/bin/pip

然后…点,点,点!

给新手Pythoneers的最后提示:开始时您不需要虚拟环境,但是以后会很高兴的。帮助开源/共享软件包的“假设情况”安装/升级方案。

参考:https : //virtualenv.pypa.io/en/latest/installation.html

Assuming you are in a highly restricted computer env (such as myself) without root access or ability to install packages…

I had never setup a fresh/standalone/raw/non-root instance of Python+virtualenv before this post. I had do quite a bit of Googling to make this work.

  1. Decide if you are using python (python2) or python3 and set your PATH correctly. (I am strictly a python3 user.) All commands below can substitute python3 for python if you are python2 user.
  2. wget https://pypi.python.org/packages/source/v/virtualenv/virtualenv-x.y.z.tar.gz
  3. tar -xzvf virtualenv-x.y.z.tar.gz
  4. python3 virtualenv-x.y.z/virtualenv.py --python $(which python3) /path/to/new/virtualenv
  5. source /path/to/new/virtualenv/bin/activate
    • Assumes you are using a Bourne-compatible shell, e.g., bash
    • Brilliantly, this virtualenv package includes a standalone version of pip and setuptools that are auto-magically installed into each new virtualenv. This solves the chicken and egg problem.
    • You may want to create an alias (or update your ~/.bashrc, etc.) for this final command to activate the python virtualenv during each login. It can be a pain to remember all these paths and commands.
  6. Check your version of python now: which python3 should give: /path/to/new/virtualenv/bin/python3
  7. Check pip is also available in the virtualenv via which pip… should give: /path/to/new/virtualenv/bin/pip

Then… pip, pip, pip!

Final tip to newbie Pythoneers: You don’t think you need virtualenv when you start, but you will be happy to have it later. Helps with “what if” installation / upgrade scenarios for open source / shared packages.

Ref: https://virtualenv.pypa.io/en/latest/installation.html


回答 15

pip在您安装Python时一起安装。您可以使用 sudo pip install (module)python3 -m pip install (module)

pip is installed together when you install Python. You can use sudo pip install (module) or python3 -m pip install (module).


回答 16

要安装pip,请安全下载get-pip.py

然后运行以下命令:

python get-pip.py

如果您使用的是由操作系统或其他程序包管理器管理的Python安装,请务必谨慎。get-pip.py与这些工具不协调,可能会使您的系统处于不一致状态。

参考:PIP安装

To install pip, securely download get-pip.py.

Then run the following:

python get-pip.py

Be cautious if you’re using a Python install that’s managed by your operating system or another package manager. get-pip.py does not coordinate with those tools, and may leave your system in an inconsistent state.

Refer: PIP Installation


回答 17

对于Windows 8.1 / 10 OS用户,只需打开 cmd(命令提示符)

写这个: C:\Users\%USERNAME%\AppData\Local\Programs\Python\Python36-32\Scripts

然后

只需这样写:pip3 install{软件包名称}

提示:Python36-32对于新的python 3.x版本,文件夹的位置可能会有所不同

And for Windows 8.1/10 OS Users just open cmd (command prompt)

write this : C:\Users\%USERNAME%\AppData\Local\Programs\Python\Python36-32\Scripts

then

just write this : pip3 install {name of package}

Hint: the location of folder Python36-32 may get different for new python 3.x versions


回答 18

如果您的Linux发行版中已经安装了Python,则应该可以使用系统的软件包管理器来安装PIP。这是可取的,因为系统安装的Python版本无法与Windows和Mac上使用的get-pip.py脚本很好地配合使用。

高级打包工具(Python 2.x)

sudo apt-get install python-pip

进阶套件工具(Python 3.x)

sudo apt-get install python3-pip

pacman软件包管理器(Python 2.x)

sudo pacman -S python2-pip

pacman软件包管理器(Python 3.x)

sudo pacman -S python-pip

Yum软件包管理器(Python 2.x)

sudo yum upgrade python-setuptools
sudo yum install python-pip python-wheel

Yum软件包管理器(Python 3.x)

sudo yum install python3 python3-wheel

Dandified Yum(Python 2.x)

sudo dnf upgrade python-setuptools
sudo dnf install python-pip python-wheel

Dandified Yum(Python 3.x)

sudo dnf install python3 python3-wheel

Zypper软件包管理器(Python 2.x)

sudo zypper install python-pip python-setuptools python-wheel

Zypper软件包管理器(Python 3.x)

sudo zypper install python3-pip python3-setuptools python3-wheel

If your Linux distro came with Python already installed, you should be able to install PIP using your system’s package manager. This is preferable since system-installed versions of Python do not play nicely with the get-pip.py script used on Windows and Mac.

Advanced Package Tool (Python 2.x)

sudo apt-get install python-pip

Advanced Package Tool (Python 3.x)

sudo apt-get install python3-pip

pacman Package Manager (Python 2.x)

sudo pacman -S python2-pip

pacman Package Manager (Python 3.x)

sudo pacman -S python-pip

Yum Package Manager (Python 2.x)

sudo yum upgrade python-setuptools
sudo yum install python-pip python-wheel

Yum Package Manager (Python 3.x)

sudo yum install python3 python3-wheel

Dandified Yum (Python 2.x)

sudo dnf upgrade python-setuptools
sudo dnf install python-pip python-wheel

Dandified Yum (Python 3.x)

sudo dnf install python3 python3-wheel

Zypper Package Manager (Python 2.x)

sudo zypper install python-pip python-setuptools python-wheel

Zypper Package Manager (Python 3.x)

sudo zypper install python3-pip python3-setuptools python3-wheel

回答 19

请按照以下步骤使用pip安装python 3:

步骤1:从此处下载安装Python

步骤2:您需要下载 get-pip.py

步骤3:下载get-pip.py之后,打开命令提示符,然后转到保存get-pip.py文件的目录。

步骤4:输入命令 python get-pip.py在cmd中。

步骤5:Pip安装成功,通过cmd中的type命令验证pip安装 pip --version

Please follow below steps to install python 3 with pip:

Step 1 : Install Python from download here

Step 2 : you’ll need to download get-pip.py

Step 3 : After download get-pip.py , open your commant prompt and go to directory where your get-pip.py file saved .

Step 4 : Enter command python get-pip.py in cmd.

Step 5 : Pip installed successfully , Verify pip installation by type command in cmd pip --version


回答 20

这是我复制粘贴的单线。

curl https://bootstrap.pypa.io/get-pip.py | python3

使用get-pip.py安装

要安装pip,请get-pip.py通过以下链接安全下载: get-pip.py。或者,使用curl:

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

然后在下载了get-pip.py的文件夹中运行以下命令:

python get-pip.py

警告:如果您使用的是由操作系统或其他程序包管理器管理的Python安装,请务必谨慎。get-pip.py与这些工具不协调,可能会使您的系统处于不一致状态。

This is the one-liner I copy-and-paste.

curl https://bootstrap.pypa.io/get-pip.py | python3

From Installing with get-pip.py:

To install pip, securely download get-pip.py by following this link: get-pip.py. Alternatively, use curl:

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

Then run the following command in the folder where you have downloaded get-pip.py:

python get-pip.py

Warning: Be cautious if you are using a Python install that is managed by your operating system or another package manager. get-pip.py does not coordinate with those tools, and may leave your system in an inconsistent state.


即使使用__init__.py,也如何解决“尝试以非软件包方式进行相对导入”

问题:即使使用__init__.py,也如何解决“尝试以非软件包方式进行相对导入”

我正在尝试使用以下目录结构来遵循PEP 328

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

core_test.py我有以下进口声明

from ..components.core import GameLoopEvents

但是,当我运行时,出现以下错误:

tests$ python core_test.py 
Traceback (most recent call last):
  File "core_test.py", line 3, in <module>
    from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package

到处搜索时,我发现“ 即使使用__init__.py,相对路径也无法使用 ”和“ 从相对路径导入模块 ”,但是它们没有帮助。

我在这里想念什么吗?

I’m trying to follow PEP 328, with the following directory structure:

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

In core_test.py I have the following import statement

from ..components.core import GameLoopEvents

However, when I run, I get the following error:

tests$ python core_test.py 
Traceback (most recent call last):
  File "core_test.py", line 3, in <module>
    from ..components.core import GameLoopEvents
ValueError: Attempted relative import in non-package

Searching around I found “relative path not working even with __init__.py” and “Import a module from a relative path” but they didn’t help.

Is there anything I’m missing here?


回答 0

是。您没有将其用作包装。

python -m pkg.tests.core_test

Yes. You’re not using it as a package.

python -m pkg.tests.core_test

回答 1

详细阐述伊格纳西奥·巴斯克斯·阿布拉姆斯答案:

Python导入机制相对于__name__当前文件起作用。直接执行文件时,它没有通常的名称,但是具有"__main__"以它的名称命名。因此,相对进口无效。

您可以按照Igancio的建议使用该-m选项执行它。如果包的一部分要作为脚本运行,则还可以使用__package__属性告诉该文件在包层次结构中应具有的名称。

参见http://www.python.org/dev/peps/pep-0366/详细信息,。

To elaborate on Ignacio Vazquez-Abrams’s answer:

The Python import mechanism works relative to the __name__ of the current file. When you execute a file directly, it doesn’t have its usual name, but has "__main__" as its name instead. So relative imports don’t work.

You can, as Igancio suggested, execute it using the -m option. If you have a part of your package that is meant to be run as a script, you can also use the __package__ attribute to tell that file what name it’s supposed to have in the package hierarchy.

See http://www.python.org/dev/peps/pep-0366/ for details.


回答 2

import components.core如果将当前目录附加到,则可以直接使用sys.path

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

You can use import components.core directly if you append the current directory to sys.path:

if __name__ == '__main__' and __package__ is None:
    from os import sys, path
    sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

回答 3

这取决于您要如何启动脚本。

如果要以经典方式从命令行启动UnitTest,那就是:

python tests/core_test.py

然后,由于在这种情况下‘components’‘tests’是同级文件夹,因此您可以使用sys.path模块的insertappend方法导入相关模块。就像是:

import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents

否则,您可以使用’-m’参数启动脚本(请注意,在这种情况下,我们正在谈论一个软件包,因此,您不能使用‘.py’扩展名),即:

python -m pkg.tests.core_test

在这种情况下,您可以像以前一样简单地使用相对导入:

from ..components.core import GameLoopEvents

最后,您可以将两种方法混合使用,以便您的脚本无论调用方式如何都可以正常工作。例如:

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        from components.core import GameLoopEvents
    else:
        from ..components.core import GameLoopEvents

It depends on how you want to launch your script.

If you want to launch your UnitTest from the command line in a classic way, that is:

python tests/core_test.py

Then, since in this case ‘components’ and ‘tests’ are siblings folders, you can import the relative module either using the insert or the append method of the sys.path module. Something like:

import sys
from os import path
sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
from components.core import GameLoopEvents

Otherwise, you can launch your script with the ‘-m’ argument (note that in this case, we are talking about a package, and thus you must not give the ‘.py’ extension), that is:

python -m pkg.tests.core_test

In such a case, you can simply use the relative import as you were doing:

from ..components.core import GameLoopEvents

You can finally mix the two approaches, so that your script will work no matter how it is called. For example:

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        from components.core import GameLoopEvents
    else:
        from ..components.core import GameLoopEvents

回答 4

在core_test.py中,执行以下操作:

import sys
sys.path.append('../components')
from core import GameLoopEvents

In core_test.py, do the following:

import sys
sys.path.append('../components')
from core import GameLoopEvents

回答 5

如果您的用例是用于运行测试的,并且可以接缝,那么您可以执行以下操作。不要像python core_test.py使用那样运行测试框架来运行测试脚本pytest。然后在命令行上您可以输入

$$ py.test

这将在您的目录中运行测试。这得到周围人的问题__name__的存在__main__,是由@BrenBarn指出。接下来,将一个空__init__.py文件放入您的测试目录,这将使测试目录成为您程序包的一部分。那你就可以做

from ..components.core import GameLoopEvents

但是,如果您将测试脚本作为主程序运行,那么事情将再次失败。因此,只需使用测试运行器。也许这也适用于其他测试运行程序,例如,nosetests但我尚未检查。希望这可以帮助。

If your use case is for running tests, and it seams that it is, then you can do the following. Instead of running your test script as python core_test.py use a testing framework such as pytest. Then on the command line you can enter

$$ py.test

That will run the tests in your directory. This gets around the issue of __name__ being __main__ that was pointed out by @BrenBarn. Next, put an empty __init__.py file into your test directory, this will make the test directory part of your package. Then you will be able to do

from ..components.core import GameLoopEvents

However, if you run your test script as a main program then things will fail once again. So just use the test runner. Maybe this also works with other test runners such as nosetests but i haven’t checked it. Hope this helps.


回答 6

我的快速解决方案是将目录添加到路径:

import sys
sys.path.insert(0, '../components/')

My quick-fix is to add the directory to the path:

import sys
sys.path.insert(0, '../components/')

回答 7

问题在于您的测试方法,

你试过了 python core_test.py

那么您将收到此错误 ValueError:尝试在非包中进行相对导入

原因:您正在从非包装来源测试包装。

因此,请从软件包源测试模块。

如果这是您的项目结构,

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

cd pkg

python -m tests.core_test # dont use .py

或从外部pkg /

python -m pkg.tests.core_test

.如果要从同一目录中的文件夹导入,则为Single 。每退一步,再增加一个。

hi/
  hello.py
how.py

how.py

from .hi import hello

如果你想从hello.py导入

from .. import how

Issue is with your testing method,

you tried python core_test.py

then you will get this error ValueError: Attempted relative import in non-package

Reason: you are testing your packaging from non-package source.

so test your module from package source.

if this is your project structure,

pkg/
  __init__.py
  components/
    core.py
    __init__.py
  tests/
    core_test.py
    __init__.py

cd pkg

python -m tests.core_test # dont use .py

or from outside pkg/

python -m pkg.tests.core_test

single . if you want to import from folder in same directory . for each step back add one more.

hi/
  hello.py
how.py

in how.py

from .hi import hello

incase if you want to import how from hello.py

from .. import how

回答 8

旧线程。我发现__all__= ['submodule', ...]__init__.py文件中添加,然后from <CURRENT_MODULE> import *在目标中使用可以正常工作。

Old thread. I found out that adding an __all__= ['submodule', ...] to the __init__.py file and then using the from <CURRENT_MODULE> import * in the target works fine.


回答 9

您可以使用from pkg.components.core import GameLoopEvents,例如我使用pycharm,下面是我的项目结构图像,我只是从根包中导入,然后就可以了:

You can use from pkg.components.core import GameLoopEvents, for example I use pycharm, the below is my project structure image, I just import from the root package, then it works:


回答 10

正如Paolo所说,我们有2种调用方法:

1) python -m tests.core_test
2) python tests/core_test.py

它们之间的区别是sys.path [0]字符串。由于解释将在导入时搜索sys.path,因此我们可以使用tests/core_test.py

if __name__ == '__main__':
    import sys
    from pathlib import Path
    sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
    from components import core
    <other stuff>

之后,我们可以使用其他方法运行core_test.py:

cd tests
python core_test.py
python -m core_test
...

注意,py36仅经过测试。

As Paolo said, we have 2 invocation methods:

1) python -m tests.core_test
2) python tests/core_test.py

One difference between them is sys.path[0] string. Since the interpret will search sys.path when doing import, we can do with tests/core_test.py:

if __name__ == '__main__':
    import sys
    from pathlib import Path
    sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
    from components import core
    <other stuff>

And more after this, we can run core_test.py with other methods:

cd tests
python core_test.py
python -m core_test
...

Note, py36 tested only.


回答 11

这种方法对我有用,并且比某些解决方案更混乱:

try:
  from ..components.core import GameLoopEvents
except ValueError:
  from components.core import GameLoopEvents

父目录位于我的PYTHONPATH中,并且__init__.py父目录和此目录中都有文件。

上面的代码始终在python 2中有效,但是python 3有时会遇到ImportError或ModuleNotFoundError(后者在python 3.6中是新功能,是ImportError的子类),因此以下调整对我在python 2和3中均有效:

try:
  from ..components.core import GameLoopEvents
except ( ValueError, ImportError):
  from components.core import GameLoopEvents

This approach worked for me and is less cluttered than some solutions:

try:
  from ..components.core import GameLoopEvents
except ValueError:
  from components.core import GameLoopEvents

The parent directory is in my PYTHONPATH, and there are __init__.py files in the parent directory and this directory.

The above always worked in python 2, but python 3 sometimes hit an ImportError or ModuleNotFoundError (the latter is new in python 3.6 and a subclass of ImportError), so the following tweak works for me in both python 2 and 3:

try:
  from ..components.core import GameLoopEvents
except ( ValueError, ImportError):
  from components.core import GameLoopEvents

回答 12

尝试这个

import components
from components import *

Try this

import components
from components import *

回答 13

如果有人正在寻找解决方法,我偶然发现了一个。这里有一些背景。我想测试文件中的一种方法。当我从内部运行时

if __name__ == "__main__":

它总是抱怨相对进口。我尝试应用上述解决方案,但由于许多嵌套文件,每个文件都有多个导入,因此无法正常工作。

这就是我所做的。我刚刚创建了一个启动器,一个外部程序,它将导入必要的方法并调用它们。虽然这不是一个很好的解决方案,但它可以工作。

If someone is looking for a workaround, I stumbled upon one. Here’s a bit of context. I wanted to test out one of the methods I’ve in a file. When I run it from within

if __name__ == "__main__":

it always complained of the relative imports. I tried to apply the above solutions, but failed to work, since there were many nested files, each with multiple imports.

Here’s what I did. I just created a launcher, an external program that would import necessary methods and call them. Though, not a great solution, it works.


回答 14

这是一种会惹恼所有人但效果很好的方法。在测试中运行:

ln -s ../components components

然后只需像往常一样导入组件。

Here’s one way which will piss off everyone but work pretty well. In tests run:

ln -s ../components components

Then just import components like you normally would.


回答 15

这非常令人困惑,如果您使用的是像pycharm这样的IDE,那就更令人困惑了。对我有用的方法:1.进行pycharm项目设置(如果从VE或python目录运行python)2.定义的方式没有错。有时它与from folder1.file1导入类一起使用

如果它不起作用,请使用import folder1.file1。3.您的环境变量应在系统中正确提及或在命令行参数中提供。

This is very confusing, and if you are using IDE like pycharm, it’s little more confusing. What worked for me: 1. Make pycharm project settings (if you are running python from a VE or from python directory) 2. There is no wrong the way you defined. sometime it works with from folder1.file1 import class

if it does not work, use import folder1.file1 3. Your environment variable should be correctly mentioned in system or provide it in your command line argument.


回答 16

由于您的代码包含if __name__ == "__main__",而不会作为包导入,因此最好使用它sys.path.append()来解决问题。

Because your code contains if __name__ == "__main__", which doesn’t be imported as a package, you’d better use sys.path.append() to solve the problem.


__init__.py的作用是什么?

问题:__init__.py的作用是什么?

什么是__init__.py一个Python源目录?

What is __init__.py for in a Python source directory?


回答 0

它曾经是软件包的必需部分(旧的3.3之前的“常规软件包”,而不是新的3.3+“命名空间软件包”)。

这是文档。

Python定义了两种类型的程序包,常规程序包和命名空间程序包。常规软件包是Python 3.2及更早版本中存在的传统软件包。常规软件包通常实现为包含__init__.py文件的目录。导入常规程序包时,__init__.py将隐式执行此文件,并将其定义的对象绑定到程序包命名空间中的名称。该__init__.py文件可以包含任何其他模块可以包含的相同Python代码,并且Python在导入时会向该模块添加一些其他属性。

但是只需单击链接,它就会包含一个示例,更多信息以及对命名空间包的说明,这些命名空间包不含__init__.py

It used to be a required part of a package (old, pre-3.3 “regular package”, not newer 3.3+ “namespace package”).

Here’s the documentation.

Python defines two types of packages, regular packages and namespace packages. Regular packages are traditional packages as they existed in Python 3.2 and earlier. A regular package is typically implemented as a directory containing an __init__.py file. When a regular package is imported, this __init__.py file is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The __init__.py file can contain the same Python code that any other module can contain, and Python will add some additional attributes to the module when it is imported.

But just click the link, it contains an example, more information, and an explanation of namespace packages, the kind of packages without __init__.py.


回答 1

命名__init__.py的文件用于将磁盘上的目录标记为Python软件包目录。如果您有文件

mydir/spam/__init__.py
mydir/spam/module.py

并且mydir在您的路径上,您可以将代码导入module.py

import spam.module

要么

from spam import module

如果删除该__init__.py文件,Python将不再在该目录中查找子模块,因此尝试导入该模块将失败。

__init__.py文件通常为空,但可用于以更方便的名称导出包的选定部分,保留方便的功能等。给定上面的示例,可以按以下方式访问init模块的内容:

import spam

基于

Files named __init__.py are used to mark directories on disk as Python package directories. If you have the files

mydir/spam/__init__.py
mydir/spam/module.py

and mydir is on your path, you can import the code in module.py as

import spam.module

or

from spam import module

If you remove the __init__.py file, Python will no longer look for submodules inside that directory, so attempts to import the module will fail.

The __init__.py file is usually empty, but can be used to export selected portions of the package under more convenient name, hold convenience functions, etc. Given the example above, the contents of the init module can be accessed as

import spam

based on this


回答 2

除了将目录标记为Python软件包并定义之外__all__,还__init__.py允许您在软件包级别定义任何变量。如果程序包定义了将以类似于API的方式频繁导入的内容,则这样做通常很方便。这种模式促进了对Pythonic的“扁平优于嵌套”哲学的坚持。

一个例子

这是我的一个项目的示例,在该项目中,我经常导入sessionmaker被叫Session以与数据库交互。我写了一个带有一些模块的“数据库”包:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

__init__.py包含以下代码:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

既然我Session在这里定义,就可以使用以下语法开始新的会话。此代码将从“数据库”包目录的内部或外部执行相同。

from database import Session
session = Session()

当然,这是一个小方便—替代方法是Session在数据库包中的新文件(例如“ create_session.py”)中定义,然后使用以下命令启动新会话:

from database.create_session import Session
session = Session()

进一步阅读

有一个非常有趣的reddit线程,涵盖了__init__.py此处的适当用法:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

大多数人似乎认为__init__.py文件应该非常薄,以避免违反“显式优于隐式”的哲学。

In addition to labeling a directory as a Python package and defining __all__, __init__.py allows you to define any variable at the package level. Doing so is often convenient if a package defines something that will be imported frequently, in an API-like fashion. This pattern promotes adherence to the Pythonic “flat is better than nested” philosophy.

An example

Here is an example from one of my projects, in which I frequently import a sessionmaker called Session to interact with my database. I wrote a “database” package with a few modules:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

My __init__.py contains the following code:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Since I define Session here, I can start a new session using the syntax below. This code would be the same executed from inside or outside of the “database” package directory.

from database import Session
session = Session()

Of course, this is a small convenience — the alternative would be to define Session in a new file like “create_session.py” in my database package, and start new sessions using:

from database.create_session import Session
session = Session()

Further reading

There is a pretty interesting reddit thread covering appropriate uses of __init__.py here:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

The majority opinion seems to be that __init__.py files should be very thin to avoid violating the “explicit is better than implicit” philosophy.


回答 3

有两个主要原因 __init__.py

  1. 为方便起见:其他用户将不需要知道您的函数在包层次结构中的确切位置。

    your_package/
      __init__.py
      file1.py
      file2.py
        ...
      fileN.py
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    # in file1.py
    def add():
        pass

    然后其他人可以通过以下方式调用add()

    from your_package import add

    不知道file1,例如

    from your_package.file1 import add
  2. 如果您想初始化一些东西;例如,日志记录(应放在顶层):

    import logging.config
    logging.config.dictConfig(Your_logging_config)

There are 2 main reasons for __init__.py

  1. For convenience: the other users will not need to know your functions’ exact location in your package hierarchy.

    your_package/
      __init__.py
      file1.py
      file2.py
        ...
      fileN.py
    
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    
    # in file1.py
    def add():
        pass
    

    then others can call add() by

    from your_package import add
    

    without knowing file1, like

    from your_package.file1 import add
    
  2. If you want something to be initialized; for example, logging (which should be put in the top level):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    

回答 4

__init__.py文件使Python将包含它的目录视为模块。

此外,这是要在模块中加载的第一个文件,因此您可以使用它来执行每次加载模块时要运行的代码,或指定要导出的子模块。

The __init__.py file makes Python treat directories containing it as modules.

Furthermore, this is the first file to be loaded in a module, so you can use it to execute code that you want to run each time a module is loaded, or specify the submodules to be exported.


回答 5

从Python 3.3开始,__init__.py不再需要将目录定义为可导入的Python包。

检查PEP 420:隐式命名空间包

对不需要__init__.py标记文件并且可以自动跨越多个路径段的软件包目录的本地支持(受PEP 420中所述的各种第三方方法启发,用于命名空间软件包)

这是测试:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

参考:
https
: //docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages https://www.python.org/dev/peps/pep-0420/
是__init__。 py对于Python 3中的软件包不是必需的?

Since Python 3.3, __init__.py is no longer required to define directories as importable Python packages.

Check PEP 420: Implicit Namespace Packages:

Native support for package directories that don’t require __init__.py marker files and can automatically span multiple path segments (inspired by various third party approaches to namespace packages, as described in PEP 420)

Here’s the test:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

references:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
Is __init__.py not required for packages in Python 3?


回答 6

在Python中,包的定义非常简单。像Java一样,层次结构和目录结构相同。但是您必须将__init__.py其打包。我将__init__.py用以下示例解释该文件:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py只要存在就可以为空。它指示该目录应视为一个包。当然__init__.py也可以设置适当的内容。

如果我们在module_n1中添加一个函数:

def function_X():
    print "function_X in module_n1"
    return

运行后:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

然后,我们遵循层次结构包,并将module_n1称为函数。我们可以__init__.py像这样在subPackage_b中使用:

__all__ = ['module_n2', 'module_n3']

运行后:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

因此,使用*导入,模块包受__init__.py内容的约束。

In Python the definition of package is very simple. Like Java the hierarchical structure and the directory structure are the same. But you have to have __init__.py in a package. I will explain the __init__.py file with the example below:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py can be empty, as long as it exists. It indicates that the directory should be regarded as a package. Of course, __init__.py can also set the appropriate content.

If we add a function in module_n1:

def function_X():
    print "function_X in module_n1"
    return

After running:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

Then we followed the hierarchy package and called module_n1 the function. We can use __init__.py in subPackage_b like this:

__all__ = ['module_n2', 'module_n3']

After running:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

Hence using * importing, module package is subject to __init__.py content.


回答 7

尽管Python在没有__init__.py文件的情况下仍可工作,但您仍应包含一个文件。

它指定应将程序包视为模块,因此将其包括在内(即使它为空)。

在某些情况下,您实际上可能会使用__init__.py文件:

假设您具有以下文件结构:

main_methods 
    |- methods.py

methods.py包含以下内容:

def foo():
    return 'foo'

要使用,foo()您需要以下条件之一:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

也许您需要(或想要)保留methods.py在内部main_methods(例如,运行时/依赖项),但只想导入main_methods


如果将的名称更改为methods.py__init__.pyfoo()只需导入即可使用main_methods

import main_methods
print(main_methods.foo()) # Prints 'foo'

这是有效的,因为__init__.py它被视为包装的一部分。


一些Python软件包实际上是这样做的。以JSON为例,其中running import json实际上是__init__.pyjson包中导入的(请参阅此处的包文件结构):

源代码: Lib/json/__init__.py

Although Python works without an __init__.py file you should still include one.

It specifies a package should be treated as a module, so therefore include it (even if it is empty).

There is also a case where you may actually use an __init__.py file:

Imagine you had the following file structure:

main_methods 
    |- methods.py

And methods.py contained this:

def foo():
    return 'foo'

To use foo() you would need one of the following:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

Maybe there you need (or want) to keep methods.py inside main_methods (runtimes/dependencies for example) but you only want to import main_methods.


If you changed the name of methods.py to __init__.py then you could use foo() by just importing main_methods:

import main_methods
print(main_methods.foo()) # Prints 'foo'

This works because __init__.py is treated as part of the package.


Some Python packages actually do this. An example is with JSON, where running import json is actually importing __init__.py from the json package (see the package file structure here):

Source code: Lib/json/__init__.py


回答 8

__init__.py 会将其所在目录视为可加载模块。

对于喜欢阅读代码的人,我在这里添加了两位炼金术士的评论。

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

__init__.py will treat the directory it is in as a loadable module.

For people who prefer reading code, I put Two-Bit Alchemist’s comment here.

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

回答 9

它有助于导入其他python文件。当您将此文件放置在包含其他py文件的目录中(例如,东西)时,可以执行诸如import stuff.other之类的操作。

root\
    stuff\
         other.py

    morestuff\
         another.py

如果__init__.py在目录东西中没有此内容,则无法导入other.py,因为Python不知道东西的源代码在哪里,也无法将其识别为包。

It facilitates importing other python files. When you placed this file in a directory (say stuff)containing other py files, then you can do something like import stuff.other.

root\
    stuff\
         other.py

    morestuff\
         another.py

Without this __init__.py inside the directory stuff, you couldn’t import other.py, because Python doesn’t know where the source code for stuff is and unable to recognize it as a package.


回答 10

一个__init__.py文件使得进口容易。当__init__.py包中包含an时,a()可以从文件中导入函数,b.py如下所示:

from b import a

但是,没有它,您将无法直接导入。您必须修改系统路径:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a

An __init__.py file makes imports easy. When an __init__.py is present within a package, function a() can be imported from file b.py like so:

from b import a

Without it, however, you can’t import directly. You have to amend the system path:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a