标签归档:python-3.6

如何将Python的.py转换为.exe?

问题:如何将Python的.py转换为.exe?

我试图将一个相当简单的Python程序转换为可执行文件,但是找不到我想要的东西,所以我有几个问题(我正在运行Python 3.6):

到目前为止,我发现的方法如下

  1. 下载旧版本的Python并使用 pyinstaller/py2exe
  2. 在Python 3.6中设置一个虚拟环境,这将允许我执行1。
  3. 下载Python到C ++转换器并使用它。

这是我尝试过的/遇到的问题。

  • 我在安装pyinstaller所需的下载之前安装了它(pypi-something),所以它无法正常工作。下载必备文件后,pyinstaller仍然无法识别它。
  • 如果要在Python 2.7中设置virtualenv,我是否真的需要安装Python 2.7?
  • 同样,我看到的唯一的python至C ++转换器只能在Python 3.5之前工作-尝试这样做是否需要下载并使用此版本?

I’m trying to convert a fairly simple Python program to an executable and couldn’t find what I was looking for, so I have a few questions (I’m running Python 3.6):

The methods of doing this that I have found so far are as follows

  1. downloading an old version of Python and using pyinstaller/py2exe
  2. setting up a virtual environment in Python 3.6 that will allow me to do 1.
  3. downloading a Python to C++ converter and using that.

Here is what I’ve tried/what problems I’ve run into.

  • I installed pyinstaller before the required download before it (pypi-something) so it did not work. After downloading the prerequisite file, pyinstaller still does not recognize it.
  • If I’m setting up a virtualenv in Python 2.7, do I actually need to have Python 2.7 installed?
  • similarly, the only python to C++ converters I see work only up until Python 3.5 – do I need to download and use this version if attempting this?

回答 0

在Python 3.6中将.py转换为.exe的步骤

  1. 安装Python 3.6
  2. 安装cx_Freeze,(打开命令提示符并输入pip install cx_Freeze
  3. 安装idna,(打开命令提示符并输入pip install idna
  4. 编写一个.py名为的程序myfirstprog.py
  5. setup.py在脚本的当前目录中创建一个新的python文件。
  6. setup.py文件中,复制下面的代码并保存。
  7. 按住Shift键并在同一目录上单击鼠标右键,因此您可以打开命令提示符窗口。
  8. 在提示中,键入 python setup.py build
  9. 如果您的脚本没有错误,那么创建应用程序将没有问题。
  10. 检查新创建的文件夹build。它有另一个文件夹。在该文件夹中,您可以找到您的应用程序。运行。让自己开心。

请参阅我的博客中的原始脚本。

setup.py:

from cx_Freeze import setup, Executable

base = None    

executables = [Executable("myfirstprog.py", base=base)]

packages = ["idna"]
options = {
    'build_exe': {    
        'packages':packages,
    },    
}

setup(
    name = "<any name>",
    options = options,
    version = "<any number>",
    description = '<any description>',
    executables = executables
)

编辑:

  • 确保不要myfirstprog.py步骤4中.py创建的扩展名放在文件名中;
  • 你应该包括每import版包您.pypackages列表(例如:packages = ["idna", "os","sys"]
  • any name, any number, any descriptionsetup.py文件不应保持不变,就应该相应地改变它(例如:name = "<first_ever>", version = "0.11", description = ''
  • import你开始之前,编辑软件包必须安装第8步

Steps to convert .py to .exe in Python 3.6

  1. Install Python 3.6.
  2. Install cx_Freeze, (open your command prompt and type pip install cx_Freeze.
  3. Install idna, (open your command prompt and type pip install idna.
  4. Write a .py program named myfirstprog.py.
  5. Create a new python file named setup.py on the current directory of your script.
  6. In the setup.py file, copy the code below and save it.
  7. With shift pressed right click on the same directory, so you are able to open a command prompt window.
  8. In the prompt, type python setup.py build
  9. If your script is error free, then there will be no problem on creating application.
  10. Check the newly created folder build. It has another folder in it. Within that folder you can find your application. Run it. Make yourself happy.

See the original script in my blog.

setup.py:

from cx_Freeze import setup, Executable

base = None    

executables = [Executable("myfirstprog.py", base=base)]

packages = ["idna"]
options = {
    'build_exe': {    
        'packages':packages,
    },    
}

setup(
    name = "<any name>",
    options = options,
    version = "<any number>",
    description = '<any description>',
    executables = executables
)

EDIT:

  • be sure that instead of myfirstprog.py you should put your .pyextension file name as created in step 4;
  • you should include each imported package in your .py into packages list (ex: packages = ["idna", "os","sys"])
  • any name, any number, any description in setup.py file should not remain the same, you should change it accordingly (ex:name = "<first_ever>", version = "0.11", description = '' )
  • the imported packages must be installed before you start step 8.

回答 1

PyInstaller支持Python 3.6。

在您的Python文件夹中打开一个cmd窗口(打开命令窗口并使用cd或按住shift键,在Windows资源管理器中右键单击它,然后选择“在此处打开命令窗口”)。然后输入

pip install pyinstaller

就是这样。

使用它的最简单方法是在命令提示符下输入

pyinstaller file_name.py

有关如何使用它的更多详细信息,请查看此问题

Python 3.6 is supported by PyInstaller.

Open a cmd window in your Python folder (open a command window and use cd or while holding shift, right click it on Windows Explorer and choose ‘Open command window here’). Then just enter

pip install pyinstaller

And that’s it.

The simplest way to use it is by entering on your command prompt

pyinstaller file_name.py

For more details on how to use it, take a look at this question.


回答 2

GitHub上有一个名为auto-py-to-exe的开源项目。实际上,它也仅在内部使用PyInstaller,但由于它具有控制PyInstaller的简单GUI,因此它可能是一个舒适的选择。与其他解决方案相比,它还可以输出独立文件。他们还提供了视频,展示了如何进行设置。

界面:

输出:

There is an open source project called auto-py-to-exe on GitHub. Actually it also just uses PyInstaller internally but since it is has a simple GUI that controls PyInstaller it may be a comfortable alternative. It can also output a standalone file in contrast to other solutions. They also provide a video showing how to set it up.

GUI:

Output:


回答 3

我无法告诉您什么是最好的,但是我过去成功使用的工具是cx_Freeze。他们最近(在17年1月7日)更新到了5.0.1版,它支持Python 3.6。

这是Pypi https://pypi.python.org/pypi/cx_Freeze

该文档显示,有多种方法可以完成此操作,具体取决于您的需求。 http://cx-freeze.readthedocs.io/en/latest/overview.html

我还没有尝试过,所以我将指向一个帖子,其中讨论了执行此操作的简单方法。有些事情可能会或可能不会改变。

如何使用cx_freeze?

I can’t tell you what’s best, but a tool I have used with success in the past was cx_Freeze. They recently updated (on Jan. 7, ’17) to version 5.0.1 and it supports Python 3.6.

Here’s the pypi https://pypi.python.org/pypi/cx_Freeze

The documentation shows that there is more than one way to do it, depending on your needs. http://cx-freeze.readthedocs.io/en/latest/overview.html

I have not tried it out yet, so I’m going to point to a post where the simple way of doing it was discussed. Some things may or may not have changed though.

How do I use cx_freeze?


回答 4

我一直在我的软件包PySimpleGUI中使用Nuitka和PyInstaller。

努伊特卡 存在使tkinter与Nuikta进行编译的问题。一个项目贡献者开发了一个脚本来解决该问题。

如果您不使用tkinter,则可能对您“有效”。如果您使用的是tkinter,请这样说,我将尝试发布脚本和说明。

PyInstaller 我正在运行3.6,PyInstaller运行良好!我用来创建exe文件的命令是:

pyinstaller -wF myfile.py

-wF将创建一个EXE文件。因为我的所有程序都具有GUI,并且我不想显示命令窗口,所以-w选项将隐藏命令窗口。

这几乎就像运行用Python编写的Winforms程序一样

[2019年7月20日更新]

有使用PyInstaller的基于PySimpleGUI GUI的解决方案。它使用PySimpleGUI。它称为pysimplegui-exemaker,可以进行pip安装。

pip install PySimpleGUI-exemaker

要在安装后运行它:

python -m pysimplegui-exemaker.pysimplegui-exemaker

I’ve been using Nuitka and PyInstaller with my package, PySimpleGUI.

Nuitka There were issues getting tkinter to compile with Nuikta. One of the project contributors developed a script that fixed the problem.

If you’re not using tkinter it may “just work” for you. If you are using tkinter say so and I’ll try to get the script and instructions published.

PyInstaller I’m running 3.6 and PyInstaller is working great! The command I use to create my exe file is:

pyinstaller -wF myfile.py

The -wF will create a single EXE file. Because all of my programs have a GUI and I do not want to command window to show, the -w option will hide the command window.

This is as close to getting what looks like a Winforms program to run that was written in Python.

[Update 20-Jul-2019]

There is PySimpleGUI GUI based solution that uses PyInstaller. It uses PySimpleGUI. It’s called pysimplegui-exemaker and can be pip installed.

pip install PySimpleGUI-exemaker

To run it after installing:

python -m pysimplegui-exemaker.pysimplegui-exemaker


回答 5

现在,您可以使用PyInstaller进行转换。我甚至使用Python 3。

脚步:

  1. 启动电脑
  2. 打开命令提示符
  3. 输入命令 pip install pyinstaller
  4. 安装后,使用命令“ cd”转到工作目录。
  5. 运行命令 pyinstall <filename>

Now you can convert it by using PyInstaller. It works with even Python 3.

Steps:

  1. Fire up your PC
  2. Open command prompt
  3. Enter command pip install pyinstaller
  4. When it is installed, use the command ‘cd’ to go to the working directory.
  5. Run command pyinstall <filename>

为什么Python 3.6.1抛出AttributeError:模块’enum’没有属性’IntFlag’?

问题:为什么Python 3.6.1抛出AttributeError:模块’enum’没有属性’IntFlag’?

我刚刚为MacOS X安装了Python 3.6.1

当我尝试运行控制台(或使用Python3运行任何命令)时,抛出此错误:

  AttributeError: module 'enum' has no attribute 'IntFlag'

$ /Library/Frameworks/Python.framework/Versions/3.6/bin/python3  
Failed to import the site module  
Traceback (most recent call last):  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 544, in <module>  
    main()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 530, in main  
    known_paths = addusersitepackages(known_paths)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 282, in addusersitepackages  
    user_site = getusersitepackages()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 258, in getusersitepackages  
    user_base = getuserbase() # this will also set USER_BASE  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 248, in getuserbase  
    USER_BASE = get_config_var('userbase')  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 601, in get_config_var  
    return get_config_vars().get(name)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 580, in get_config_vars  
    import _osx_support  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_osx_support.py", line 4, in <module>  
    import re  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.py", line 142, in <module>  
    class RegexFlag(enum.IntFlag):  
AttributeError: module 'enum' has no attribute 'IntFlag'  

IntFlag类存在于enum.py中。那么,为什么会抛出AttributeError?

I just installed Python 3.6.1 for MacOS X

When I attempt to run the Console(or run anything with Python3), this error is thrown:

  AttributeError: module 'enum' has no attribute 'IntFlag'

$ /Library/Frameworks/Python.framework/Versions/3.6/bin/python3  
Failed to import the site module  
Traceback (most recent call last):  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 544, in <module>  
    main()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 530, in main  
    known_paths = addusersitepackages(known_paths)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 282, in addusersitepackages  
    user_site = getusersitepackages()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 258, in getusersitepackages  
    user_base = getuserbase() # this will also set USER_BASE  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 248, in getuserbase  
    USER_BASE = get_config_var('userbase')  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 601, in get_config_var  
    return get_config_vars().get(name)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 580, in get_config_vars  
    import _osx_support  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_osx_support.py", line 4, in <module>  
    import re  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.py", line 142, in <module>  
    class RegexFlag(enum.IntFlag):  
AttributeError: module 'enum' has no attribute 'IntFlag'  

The class IntFlag exists within enum.py. So, why is the AttributeError being thrown?


回答 0

这是因为您enum不是标准库enum模块。您可能已经enum34安装了软件包。

检查是否属于这种情况的一种方法是检查物业 enum.__file__

import enum
print(enum.__file__)  
# standard library location should be something like 
# /usr/local/lib/python3.6/enum.py

从python 3.6开始,enum34库不再与标准库兼容。该库也是不必要的,因此您可以简单地将其卸载。

pip uninstall -y enum34

如果您需要代码在<= 3.4和> 3.4的python版本上运行,则可以enum-compat根据需要尝试。它仅enum34针对没有标准库枚举的python较旧版本安装。

It’s because your enum is not the standard library enum module. You probably have the package enum34 installed.

One way check if this is the case is to inspect the property enum.__file__

import enum
print(enum.__file__)  
# standard library location should be something like 
# /usr/local/lib/python3.6/enum.py

Since python 3.6 the enum34 library is no longer compatible with the standard library. The library is also unnecessary, so you can simply uninstall it.

pip uninstall -y enum34

If you need the code to run on python versions both <=3.4 and >3.4, you can try having enum-compat as a requirement. It only installs enum34 for older versions of python without the standard library enum.


回答 1

不知道您是否仍然有此问题。我遇到了类似的问题,只需取消设置即可解决PYTHONPATH

$ unset PYTHONPATH

Not sure whether you still have this issue. I had a similar issue and I was able to resolve it simply by unsetting PYTHONPATH

$ unset PYTHONPATH


回答 2

对我来说,此错误是在安装gcloud组件app-engine-python以便集成到pycharm后发生的。即使pycharm现在不上传到app-engine,卸载模块也有帮助。

For me this error occured after installing of gcloud component app-engine-python in order to integrate into pycharm. Uninstalling the module helped, even if pycharm is now not uploading to app-engine.


回答 3

如果有人在PyCharm中运行Google App Engine Python 3.7标准环境项目时由于遇到此错误而来这里,那么您所需要做的就是

  • 确保要运行的配置适用于Flask,而不适用于Google App Engine配置。
  • 然后在偏好设置>>语言和框架>> Google App Engine下禁用Google App Engine支持

原因是根据此链接

总体目标是您的应用程序应具有完全可移植性,并可以在任何标准Python环境中运行。您编写的是标准Python应用程序,而不是App Engine Python应用程序。作为此转变的一部分,您不再需要为应用程序的核心功能使用专有的App Engine API和服务。目前,Python 3.7运行时中不提供App Engine API。

我猜想当我们在PyCharm中将python 3.7项目创建为Google应用引擎项目时,它仍会尝试以与python2.7应用相同的方式进行操作

If anyone coming here because of getting this error while running a google app engine Python 3.7 standard environment project in PyCharm then all you need to do is

  • Make sure the configuration to run is for Flask, not Google App Engine configuration.
  • Then disable Google App Engine support under Preferences >> Languages & Framework >> Google App Engine

The reason being as per this link

The overall goal is that your app should be fully portable and run in any standard Python environment. You write a standard Python app, not an App Engine Python app. As part of this shift, you are no longer required to use proprietary App Engine APIs and services for your app’s core functionality. At this time, App Engine APIs are not available in the Python 3.7 runtime.

I guess when we create a python 3.7 project in PyCharm as a Google app engine project it still tries to do the same way it does for a python2.7 app


回答 4

免责声明:请@ juanpa.arrivillaga,如果您看到此答案,请随时写自己的答案,我将删除此帖子。

@ juanpa.arrivillaga 上面已经提到过

您的工作目录中是否有文件名enum.py?

这就是我遇到的问题。我当时还不知道python上的enum模块,并已命名我的测试文件enum.py

由于文件名模块名,因此存在冲突。有关模块的更多信息,请参见:https : //docs.python.org/2/tutorial/modules.html

DISCLAIMER: Please, @juanpa.arrivillaga, if you see this answer, feel free to write your own and I will remove this post.

@juanpa.arrivillaga had mentioned above:

Is there a file name enum.py in your working directory, by any chance?

This was the issue I encountered. I was not aware of the enum module on python at the time and had named my test file enum.py.

Since the file name is the module name, there was a conflict. More info on modules here: https://docs.python.org/2/tutorial/modules.html


回答 5

在pycharm首选项中禁用“ Google App Engine支持”对我来说解决了这个问题。

Disabling “Google App Engine Support” in pycharm preferences fixed this issue for me.


回答 6

HåkenLid的回答帮助解决了我的问题(谢谢!),在本例中,在运行于Docker容器中的Flask的Python3.7中FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7

就我而言,enum34是由另一个库(pip install smartsheet-python-sdk)安装的。对于那些遇到类似Docker容器问题的人,这是我的最终Dockerfile(跳至相关行):

FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7
...
RUN pip install -r requirements.txt
RUN pip uninstall -y enum34
...

Håken Lid’s answer helped solved my problem (thanks!) , in my case present in Python3.7 running Flask in a Docker container (FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7).

In my case, enum34 was being installed by another library (pip install smartsheet-python-sdk). For those coming with a similar Docker container problem, here is my final Dockerfile (stripped to the relevant lines):

FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7
...
RUN pip install -r requirements.txt
RUN pip uninstall -y enum34
...

回答 7

如果必须同时为python2和python3保留PYTHONPATH,则可以编写别名语句以在bash_profile中设置适当的PYTHONPATH:

在〜/ .bash_profile中,对PYTHONPATH2和PYTHONPATH3变量进行硬编码,并在其末尾添加以下别名:

alias python='export PYTHONPATH=${PYTHONPATH2};python'
alias python3='export PYTHONPATH=${PYTHONPATH3};python3'

python(指python2),因为我更经常使用python2。

In case you have to keep PYTHONPATH for both python2 and python3, you can write alias statements to set the proper PYTHONPATH in your bash_profile:

Hardcode your PYTHONPATH2, and PYTHONPATH3 variables in your ~/.bash_profile, and add the following aliases at the end of it:

alias python='export PYTHONPATH=${PYTHONPATH2};python'
alias python3='export PYTHONPATH=${PYTHONPATH3};python3'

My python (refers to python2) as I use python2 more often.


回答 8

每当我遇到这个问题时:

AttributeError:模块“枚举”没有属性“ IntFlag”

只需首先运行命令:

unset PYTHONPATH 

然后运行我想要的命令,然后在其中成功。

When ever I got this problem:

AttributeError: module ‘enum’ has no attribute ‘IntFlag’

simply first i run the command:

unset PYTHONPATH 

and then run my desired command then got success in that.


回答 9

使用pip install <required-library> --ignore-installed enum34
安装所需的库后,在构建过程中查找警告。我收到这样的错误:
Using legacy setup.py install for future, since package 'wheel' is not installed
ERROR: pyejabberd 0.2.11 has requirement enum34==1.1.2, but you'll have enum34 1.1.10 which is incompatible.

要解决此问题,请运行以下命令:pip freeze | grep enum34。这将为您提供已安装的enum34的版本。现在将其卸载,pip uninstall enum34然后重新安装所需的版本
pip install "enum34==1.1.20"

I did by using pip install <required-library> --ignore-installed enum34
Once your required library is installed, look for warnings during the build. I got an Error like this:
Using legacy setup.py install for future, since package 'wheel' is not installed
ERROR: pyejabberd 0.2.11 has requirement enum34==1.1.2, but you'll have enum34 1.1.10 which is incompatible.

To fix this issue now run the command: pip freeze | grep enum34. This will give you the version of the installed enum34. Now uninstall it by pip uninstall enum34 and reinstall the required version as
pip install "enum34==1.1.20"


回答 10

我的计算机上安装了Python 2和Python 3。由于某些奇怪的原因,当调用re模块时,我在Python 3的sys.path中也有一个指向Python2的sitepackage库目录的路径。如果我运行Python 3并导入枚举,print(enum.__file__)并且系统未显示此Python 2站点包路径。因此,一个非常粗糙和肮脏的技巧是直接修改导入枚举的模块(遵循回溯路径)并在导入枚举之前插入以下代码:

import sys
for i, p in enumerate(sys.path):
    if "python27" in p.lower() or "python2.7" in p.lower(): sys.path.pop(i)
import enum

那解决了我的问题。

I have Python 2 and Python 3 installed on my computer. For some strange reason I have in the sys.path of Python 3 also a path to the sitepackage library directory of Python2 when the re module is called. If I run Python 3 and import enum and print(enum.__file__) the system does not show this Python 2 path to site-packages. So a very rough and dirty hack is, to directly modify the module in which enum is imported (follow the traceback paths) and insert the following code just before importing enum:

import sys
for i, p in enumerate(sys.path):
    if "python27" in p.lower() or "python2.7" in p.lower(): sys.path.pop(i)
import enum

That solved my problem.


回答 11

安装enum34的1.1.8版本对我有用。

我能够通过向pyproject.toml添加enum34 =“ == 1.1.8”来解决此问题。显然enum34在v1.1.8中具有避免此错误的功能,但在v1.1.9 +中已退步。不过,这只是一种解决方法。更好的解决方案是使程序包使用环境标记,因此除非需要,您根本不需要安装enum34。

来源:https//github.com/python-poetry/poetry/issues/1122

Installing version 1.1.8 of enum34 worked for me.

I was able to fix this by adding enum34 = “==1.1.8” to pyproject.toml. Apparently enum34 had a feature in v1.1.8 that avoided this error, but this regressed in v1.1.9+. This is just a workaround though. The better solution would be for packages to use environment markers so you don’t have to install enum34 at all unless needed.

Source: https://github.com/python-poetry/poetry/issues/1122


回答 12

即使我在运行python -m grpc_tools.protoc –version时遇到了这个问题,也必须设置PYTHONPATH直到站点包并关闭所有命令提示符窗口,然后它才能工作。希望它对gRPC用户有所帮助。

Even I had this issue while running python -m grpc_tools.protoc –version Had to set the PYTHONPATH till site-packages and shutdown all the command prompt windows and it worked. Hope it helps for gRPC users.


回答 13

我在使用python3.8和tensorflow 2.2.0的虚拟环境内核中的jupyterlab的ubuntu20.04中遇到了这个问题。错误消息原为

 Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel_launcher.py", line 15, in <module>
    from ipykernel import kernelapp as app
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/__init__.py", line 2, in <module>
    from .connect import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/connect.py", line 13, in <module>
    from IPython.core.profiledir import ProfileDir
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/__init__.py", line 48, in <module>
    from .core.application import Application
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/core/application.py", line 23, in <module>
    from traitlets.config.application import Application, catch_config_error
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/__init__.py", line 1, in <module>
    from .traitlets import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/traitlets.py", line 49, in <module>
    import enum
ImportError: No module named enum

问题是在/ usr / bin / python中的符号链接中指向python2。解:

cd /usr/bin/
sudo ln -sf python3 python

我希望python2快死了!马库斯Terveisin

I had this problem in ubuntu20.04 in jupyterlab in my virtual env kernel with python3.8 and tensorflow 2.2.0. Error message was

 Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel_launcher.py", line 15, in <module>
    from ipykernel import kernelapp as app
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/__init__.py", line 2, in <module>
    from .connect import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/connect.py", line 13, in <module>
    from IPython.core.profiledir import ProfileDir
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/__init__.py", line 48, in <module>
    from .core.application import Application
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/core/application.py", line 23, in <module>
    from traitlets.config.application import Application, catch_config_error
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/__init__.py", line 1, in <module>
    from .traitlets import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/traitlets.py", line 49, in <module>
    import enum
ImportError: No module named enum

problem was that in symbolic link in /usr/bin/python was pointing to python2. Solution:

cd /usr/bin/
sudo ln -sf python3 python

Hopefully Python 2 usage will drop off completely soon.


回答 14

如果在运行时有这个问题测试PyCharm,确保第二个框选中的配置。

If you having this issue when running tests in PyCharm, make sure the second box is unchecked in the configurations.


回答 15

如果有人有试图从virtualenv中运行Jupyter内核的时候这个问题,只需添加正确的PYTHONPATHkernel.json您的virtualenv内核(Python 3的例子)的:

{
 "argv": [
  "/usr/local/Cellar/python/3.6.5/bin/python3.6",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "display_name": "Python 3 (TensorFlow)",
 "language": "python",
 "env": {
     "PYTHONPATH":     "/Users/dimitrijer/git/mlai/.venv/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/lib-dynload:/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/site-packages"
}
}

If anyone is having this problem when trying to run Jupyter kernel from a virtualenv, just add correct PYTHONPATH to kernel.json of your virtualenv kernel (Python 3 in example):

{
 "argv": [
  "/usr/local/Cellar/python/3.6.5/bin/python3.6",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "display_name": "Python 3 (TensorFlow)",
 "language": "python",
 "env": {
     "PYTHONPATH":     "/Users/dimitrijer/git/mlai/.venv/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/lib-dynload:/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/site-packages"
}
}

如何在f字符串中使用换行符’\ n’格式化Python 3.6中的输出?

问题:如何在f字符串中使用换行符’\ n’格式化Python 3.6中的输出?

我想知道如何用f字符串以Pythonic方式格式化这种情况:

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

问题是'\'无法在{...}f字符串的表达式部分内使用。预期Yield:

Winners are:
Adam
Bob
Cyril

I would like to know how to format this case in a Pythonic way with f-strings:

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

The problem is that '\' cannot be used inside the {...} expression portions of an f-string. Expected output:

Winners are:
Adam
Bob
Cyril

回答 0

你不能 反斜杠不能出现在花括号内{};这样做会导致SyntaxError

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

这是在PEP中为f字符串指定的:

反斜杠可能不会出现在f字符串的表达式部分内,[…]

一种选择是先'\n'命名,然后再.joinf-string 内进行命名;也就是说,不使用文字:

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

结果是:

Winners are:
Adam
Bob
Cyril

@wim指定的另一个选项是chr(10)用来获取\n返回值,然后在该处加入。f"Winners are:\n{chr(10).join(names)}"

当然,还有另一种方法是'\n'.join预先添加相应的名称:

n = "\n".join(names)
text = f"Winners are:\n{n}"

结果相同。

注意:

这是f-string和之间的细微差别之一str.format。在后者中,您可以始终使用标点符号,只要打开包含这些键的相应古怪字典即可:

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(请不要这样做。)

在前一种情况下,标点符号是不允许的,因为您不能使用它们的标识符。


撇开:我肯定会选择printformat,因为其他答案也可以替代。我给出的选项仅在由于某些原因必须使用f字符串的情况下适用。

仅仅因为有些新事物,并不意味着您应该尝试用它做一切;-)

You can’t. Backslashes cannot appear inside the curly braces {}; doing so results in a SyntaxError:

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

This is specified in the PEP for f-strings:

Backslashes may not appear inside the expression portions of f-strings, […]

One option is assinging '\n' to a name and then .join on that inside the f-string; that is, without using a literal:

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

Results in:

Winners are:
Adam
Bob
Cyril

Another option, as specified by @wim, is to use chr(10) to get \n returned and then join there. f"Winners are:\n{chr(10).join(names)}"

Yet another, of course, is to '\n'.join beforehand and then add the name accordingly:

n = "\n".join(names)
text = f"Winners are:\n{n}"

which results in the same output.

Note:

This is one of the small differences between f-strings and str.format. In the latter, you can always use punctuation granted that a corresponding wacky dict is unpacked that contains those keys:

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(Please don’t do this.)

In the former, punctuation isn’t allowed because you can’t have identifiers that use them.


Aside: I would definitely opt for print or format, as the other answers suggest as an alternative. The options I’ve given only apply if you must for some reason use f-strings.

Just because something is new, doesn’t mean you should try and do everything with it ;-)


回答 1

您不需要f字符串或其他格式化程序即可使用分隔符打印字符串列表。只需使用sep关键字参数即可print()

names = ['Adam', 'Bob', 'Cyril']
print('Winners are:', *names, sep='\n')

输出:

Winners are:
Adam
Bob
Cyril

就是说,使用str.join()/str.format()这里比任何f字符串解决方法更容易理解。

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))

You don’t need f-strings or other formatters to print a list of strings with a separator. Just use the sep keyword argument to print():

names = ['Adam', 'Bob', 'Cyril']
print('Winners are:', *names, sep='\n')

Output:

Winners are:
Adam
Bob
Cyril

That said, using str.join()/str.format() here would arguably be simpler and more readable than any f-string workaround:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))

回答 2

您不能像其他人所说的那样在f字符串中使用反斜杠,但是您可以使用来解决这个问题os.linesep(尽管请注意,并非\n在所有平台上都使用反斜杠,除非读/写二进制文件,否则不建议这样做;请参阅Rick的评论):

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

或以一种不太易读的方式,但保证是\n,方法是chr()

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril

You can’t use backslashes in f-strings as others have said, but you could step around this using os.linesep (although note this won’t be \n on all platforms, and is not recommended unless reading/writing binary files; see Rick’s comments):

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

Or perhaps in a less readable way, but guaranteed to be \n, with chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril

回答 3

其他答案给出了有关如何将换行符放入f字符串字段的想法。但是,我认为对于OP给出的示例(可能指示OP的实际用例),实际上不应该使用这些想法。

使用f字符串的全部目的是提高代码的可读性。f字符串是您无法使用的format。请仔细考虑是否对此有更多可读性(如果可以的话):

f"Winners are:\n{'\n'.join(names)}"

…或这个:

newline = '\n'
f"Winners are:\n{newline.join(names)}"

…或这个:

"Winners are:\n{chr(10).join(names)}"

与这个:

"Winners are:\n{}".format('\n'.join(names))

最后一种方法至少具有可读性,如果不是更多的话。

简而言之:当您需要螺丝起子时,不要只用锤子,因为那是新的有光泽的工具。读取代码的频率远高于写入代码。

对于其他用例,是的,这个chr(10)想法或newline想法可能是适当的。但不是给定的。

The other answers give ideas for how to put the newline character into a f-string field. However, I would argue that for the example the OP gave (which may or may not be indicative of OP’s actual use case), none of these ideas should actually be used.

The entire point of using f-strings is increasing code readability. There is nothing you can do with f-strings that you cannot do with format. Consider carefully whether there is anything more readable about this (if you could do it):

f"Winners are:\n{'\n'.join(names)}"

…or this:

newline = '\n'
f"Winners are:\n{newline.join(names)}"

…or this:

"Winners are:\n{chr(10).join(names)}"

vs. this:

"Winners are:\n{}".format('\n'.join(names))

The last way is at least as readable, if not more so.

In short: don’t use a hammer when you need a screwdriver just because you have a shiny new one. Code is read much more often than it is written.

For other use cases, yes, it’s possible the chr(10) idea or newline idea may be appropriate. But not for the one given.


如何推迟/推迟对f弦的评估?

问题:如何推迟/推迟对f弦的评估?

我正在使用模板字符串生成一些文件,为此我喜欢新的f字符串的简洁性,以减少类似以下内容的我以前的模板代码:

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print (template_a.format(**locals()))

现在,我可以直接替换变量:

names = ["foo", "bar"]
for name in names:
    print (f"The current name is {name}")

但是,有时在其他地方定义模板是有意义的-在代码中较高的位置,或者从文件或其他内容中导入模板。这意味着模板是带有格式标记的静态字符串。字符串上必须发生一些事情,以告诉解释器将字符串解释为新的f字符串,但是我不知道是否有这种事情。

有什么方法可以引入字符串并将其解释为f字符串,从而避免使用.format(**locals())调用?

理想情况下,我希望能够像这样进行编码…(magic_fstring_function我不理解的部分在哪里出现):

template_a = f"The current name is {name}"
# OR [Ideal2] template_a = magic_fstring_function(open('template.txt').read())
names = ["foo", "bar"]
for name in names:
    print (template_a)

…具有所需的输出(无需两次读取文件):

The current name is foo
The current name is bar

…但是我得到的实际输出是:

The current name is {name}
The current name is {name}

I am using template strings to generate some files and I love the conciseness of the new f-strings for this purpose, for reducing my previous template code from something like this:

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print (template_a.format(**locals()))

Now I can do this, directly replacing variables:

names = ["foo", "bar"]
for name in names:
    print (f"The current name is {name}")

However, sometimes it makes sense to have the template defined elsewhere — higher up in the code, or imported from a file or something. This means the template is a static string with formatting tags in it. Something would have to happen to the string to tell the interpreter to interpret the string as a new f-string, but I don’t know if there is such a thing.

Is there any way to bring in a string and have it interpreted as an f-string to avoid using the .format(**locals()) call?

Ideally I want to be able to code like this… (where magic_fstring_function is where the part I don’t understand comes in):

template_a = f"The current name is {name}"
# OR [Ideal2] template_a = magic_fstring_function(open('template.txt').read())
names = ["foo", "bar"]
for name in names:
    print (template_a)

…with this desired output (without reading the file twice):

The current name is foo
The current name is bar

…but the actual output I get is:

The current name is {name}
The current name is {name}

回答 0

这是完整的“理想2”。

它不是f字符串,它甚至不使用f字符串,但可以按要求进行操作。语法完全符合规定。没有使用安全性,因为我们没有使用eval()

它使用了一个小类并实现了__str__由print自动调用的类。为了逃避该类的有限范围,我们使用该inspect模块向上跳一帧并查看调用者可以访问的变量。

import inspect

class magic_fstring_function:
    def __init__(self, payload):
        self.payload = payload
    def __str__(self):
        vars = inspect.currentframe().f_back.f_globals.copy()
        vars.update(inspect.currentframe().f_back.f_locals)
        return self.payload.format(**vars)

template = "The current name is {name}"

template_a = magic_fstring_function(template)

# use it inside a function to demonstrate it gets the scoping right
def new_scope():
    names = ["foo", "bar"]
    for name in names:
        print(template_a)

new_scope()
# The current name is foo
# The current name is bar

Here’s a complete “Ideal 2”.

It’s not an f-string—it doesn’t even use f-strings—but it does as requested. Syntax exactly as specified. No security headaches since we are not using eval().

It uses a little class and implements __str__ which is automatically called by print. To escape the limited scope of the class we use the inspect module to hop one frame up and see the variables the caller has access to.

import inspect

class magic_fstring_function:
    def __init__(self, payload):
        self.payload = payload
    def __str__(self):
        vars = inspect.currentframe().f_back.f_globals.copy()
        vars.update(inspect.currentframe().f_back.f_locals)
        return self.payload.format(**vars)

template = "The current name is {name}"

template_a = magic_fstring_function(template)

# use it inside a function to demonstrate it gets the scoping right
def new_scope():
    names = ["foo", "bar"]
    for name in names:
        print(template_a)

new_scope()
# The current name is foo
# The current name is bar

回答 1

这意味着模板是带有格式标记的静态字符串

是的,这就是为什么我们要使用带有替换字段和的文字.format,因此我们可以随时调用format它来替换这些字段。

字符串上必须发生一些事情,以告知解释器将字符串解释为新的f字符串

那是前缀f/F。您可以将其包装在一个函数中,并在调用期间推迟评估,但是当然会产生额外的开销:

template_a = lambda: f"The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print (template_a())

打印出:

The current name is foo
The current name is bar

但感觉不对,并受到以下事实的限制:您只能窥视替换中的全局命名空间。在需要本地名称的情况下尝试使用它会惨遭失败,除非将其作为参数传递给字符串(这完全是关键)。

有什么方法可以引入字符串并将其解释为f字符串,从而避免使用.format(**locals())调用?

除了功能(包括限制)外,不行,所以不妨坚持.format

This means the template is a static string with formatting tags in it

Yes, that’s exactly why we have literals with replacement fields and .format, so we can replace the fields whenever we like by calling format on it.

Something would have to happen to the string to tell the interpreter to interpret the string as a new f-string

That’s the prefix f/F. You could wrap it in a function and postpone the evaluation during call time but of course that incurs extra overhead:

template_a = lambda: f"The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print (template_a())

Which prints out:

The current name is foo
The current name is bar

but feels wrong and is limited by the fact that you can only peek at the global namespace in your replacements. Trying to use it in a situation which requires local names will fail miserably unless passed to the string as arguments (which totally beats the point).

Is there any way to bring in a string and have it interpreted as an f-string to avoid using the .format(**locals()) call?

Other than a function (limitations included), nope, so might as well stick with .format.


回答 2

一种将字符串评估为f字符串(具有完整功能)的简洁方法是使用以下函数:

def fstr(template):
    return eval(f"f'{template}'")

然后,您可以执行以下操作:

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print(fstr(template_a))
# The current name is foo
# The current name is bar

并且,与许多其他建议的解决方案相比,您还可以执行以下操作:

template_b = "The current name is {name.upper() * 2}"
for name in names:
    print(fstr(template_b))
# The current name is FOOFOO
# The current name is BARBAR

A concise way to have a string evaluated as an f-string (with its full capabilities) is using following function:

def fstr(template):
    return eval(f"f'{template}'")

Then you can do:

template_a = "The current name is {name}"
names = ["foo", "bar"]
for name in names:
    print(fstr(template_a))
# The current name is foo
# The current name is bar

And, in contrast to many other proposed solutions, you can also do:

template_b = "The current name is {name.upper() * 2}"
for name in names:
    print(fstr(template_b))
# The current name is FOOFOO
# The current name is BARBAR

回答 3

一架F-string是简单的创建一个格式化字符串,更换了更为简洁的方式.format(**names)f。如果您不希望以这种方式立即评估字符串,请不要将其设置为f字符串。将其另存为普通字符串文字,然后format在以后要进行插值时再调用它,就像以前一样。

当然,可以使用替代eval

template.txt

f’当前名称为{name}’

码:

>>> template_a = open('template.txt').read()
>>> names = 'foo', 'bar'
>>> for name in names:
...     print(eval(template_a))
...
The current name is foo
The current name is bar

但后来你已经设法做的是替换str.formateval,这肯定是不值得的。只需继续使用常规字符串即可format

An f-string is simply a more concise way of creating a formatted string, replacing .format(**names) with f. If you don’t want a string to be immediately evaluated in such a manner, don’t make it an f-string. Save it as an ordinary string literal, and then call format on it later when you want to perform the interpolation, as you have been doing.

Of course, there is an alternative with eval.

template.txt:

f’The current name is {name}’

Code:

>>> template_a = open('template.txt').read()
>>> names = 'foo', 'bar'
>>> for name in names:
...     print(eval(template_a))
...
The current name is foo
The current name is bar

But then all you’ve managed to do is replace str.format with eval, which is surely not worth it. Just keep using regular strings with a format call.


回答 4

使用.format并不是此问题的正确答案。Python f字符串与str.format()模板非常不同…它们可以包含代码或其他昂贵的操作-因此需要推迟。

这是一个延迟记录器的示例。这使用了logging.getLogger的常规序言,但是随后添加了仅在日志级别正确的情况下解释f字符串的新函数。

log = logging.getLogger(__name__)

def __deferred_flog(log, fstr, level, *args):
    if log.isEnabledFor(level):
        import inspect
        frame = inspect.currentframe().f_back.f_back
        try:
            fstr = 'f"' + fstr + '"'
            log.log(level, eval(fstr, frame.f_globals, frame.f_locals))
        finally:
            del frame
log.fdebug = lambda fstr, *args: __deferred_flog(log, fstr, logging.DEBUG, *args)
log.finfo = lambda fstr, *args: __deferred_flog(log, fstr, logging.INFO, *args)

这样做的优点是能够执行以下操作: log.fdebug("{obj.dump()}")….除非启用调试,否则不转储对象。

恕我直言:这应该是f字符串的默认操作,但是现在为时已晚。F字符串评估可能会产生大量和意想不到的副作用,以延迟的方式发生会改变程序的执行。

为了适当延迟f字符串,python需要某种方式来显式切换行为。也许使用字母“ g”?;)

Using .format is not a correct answer to this question. Python f-strings are very different from str.format() templates … they can contain code or other expensive operations – hence the need for deferral.

Here’s an example of a deferred logger. This uses the normal preamble of logging.getLogger, but then adds new functions that interpret the f-string only if the log level is correct.

log = logging.getLogger(__name__)

def __deferred_flog(log, fstr, level, *args):
    if log.isEnabledFor(level):
        import inspect
        frame = inspect.currentframe().f_back.f_back
        try:
            fstr = 'f"' + fstr + '"'
            log.log(level, eval(fstr, frame.f_globals, frame.f_locals))
        finally:
            del frame
log.fdebug = lambda fstr, *args: __deferred_flog(log, fstr, logging.DEBUG, *args)
log.finfo = lambda fstr, *args: __deferred_flog(log, fstr, logging.INFO, *args)

This has the advantage of being able to do things like: log.fdebug("{obj.dump()}") …. without dumping the object unless debugging is enabled.

IMHO: This should have been the default operation of f-strings, however now it’s too late. F-string evaluation can have massive and unintended side-effects, and having that happen in a deferred manner will change program execution.

In order to make f-strings properly deferred, python would need some way of explicitly switching behavior. Maybe use the letter ‘g’? ;)

It has been pointed out that deferred logging shouldn’t crash if there’s a bug in the string converter. The above solution can do this as well, change the finally: to except:, and stick a log.exception in there.


回答 5

您想要的东西似乎被认为是Python增强功能

同时-从链接的讨论中-以下似乎是一个不需要使用的合理解决方法eval()

class FL:
    def __init__(self, func):
        self.func = func
    def __str__(self):
        return self.func()


template_a = FL(lambda: f"The current name, number is {name!r}, {number+1}")
names = "foo", "bar"
numbers = 40, 41
for name, number in zip(names, numbers):
    print(template_a)

输出:

The current name, number is 'foo', 41
The current name, number is 'bar', 42

What you want appears to be being considered as a Python enhancement.

Meanwhile — from the linked discussion — the following seems like it would be a reasonable workaround that doesn’t require using eval():

class FL:
    def __init__(self, func):
        self.func = func
    def __str__(self):
        return self.func()


template_a = FL(lambda: f"The current name, number is {name!r}, {number+1}")
names = "foo", "bar"
numbers = 40, 41
for name, number in zip(names, numbers):
    print(template_a)

Output:

The current name, number is 'foo', 41
The current name, number is 'bar', 42

回答 6

kadee答案的启发,以下内容可用于定义deferred-f-string类。

class FStr:
    def __init__(self, s):
        self._s = s
    def __repr__(self):
        return eval(f"f'{self._s}'")

...

template_a = FStr('The current name is {name}')

names = ["foo", "bar"]
for name in names:
    print (template_a)

这正是这个问题要问的

inspired by the answer by kadee, the following can be used to define a deferred-f-string class.

class FStr:
    def __init__(self, s):
        self._s = s
    def __repr__(self):
        return eval(f"f'{self._s}'")

...

template_a = FStr('The current name is {name}')

names = ["foo", "bar"]
for name in names:
    print (template_a)

which is exactly what the question asked for


回答 7

或者也许不使用f字符串,只需格式化:

fun = "The curent name is {name}".format
names = ["foo", "bar"]
for name in names:
    print(fun(name=name))

在没有名称的版本中:

fun = "The curent name is {}".format
names = ["foo", "bar"]
for name in names:
    print(fun(name))

Or maybe do not use f-strings, just format:

fun = "The curent name is {name}".format
names = ["foo", "bar"]
for name in names:
    print(fun(name=name))

In version without names:

fun = "The curent name is {}".format
names = ["foo", "bar"]
for name in names:
    print(fun(name))

回答 8

怎么样:

s = 'Hi, {foo}!'

s
> 'Hi, {foo}!'

s.format(foo='Bar')
> 'Hi, Bar!'

How about:

s = 'Hi, {foo}!'

s
> 'Hi, {foo}!'

s.format(foo='Bar')
> 'Hi, Bar!'

回答 9

使用f字符串的建议。在发生模板的逻辑级别上进行评估,并将其作为生成器传递。您可以使用f弦在任意位置解开它

In [46]: names = (i for i in ('The CIO, Reed', 'The homeless guy, Arnot', 'The security guard Spencer'))

In [47]: po = (f'Strangely, {next(names)} has a nice {i}' for i in (" nice house", " fast car", " big boat"))

In [48]: while True:  
...:     try:  
...:         print(next(po))  
...:     except StopIteration:  
...:         break  
...:       
Strangely, The CIO, Reed has a nice  nice house  
Strangely, The homeless guy, Arnot has a nice  fast car  
Strangely, The security guard Spencer has a nice  big boat  

A suggestion that uses f-strings. Do your evaluation on the logical level where the templating is occurring and pass it as a generator. You can unwind it at whatever point you choose, using f-strings

In [46]: names = (i for i in ('The CIO, Reed', 'The homeless guy, Arnot', 'The security guard Spencer'))

In [47]: po = (f'Strangely, {next(names)} has a nice {i}' for i in (" nice house", " fast car", " big boat"))

In [48]: while True:  
...:     try:  
...:         print(next(po))  
...:     except StopIteration:  
...:         break  
...:       
Strangely, The CIO, Reed has a nice  nice house  
Strangely, The homeless guy, Arnot has a nice  fast car  
Strangely, The security guard Spencer has a nice  big boat  

如何在for循环中注释类型

问题:如何在for循环中注释类型

我想在for-loop中注释变量的类型。我尝试了这个:

for i: int in range(5):
    pass

但这显然没有用。

我期望在PyCharm 2016.3.2中能够自动完成工作。像这样的预注释:

i: int
for i in range(5):
    pass

没有帮助。

适用于PyCharm> = 2017.1的PS预注释作品

I want to annotate a type of a variable in a for-loop. I tried this:

for i: int in range(5):
    pass

But it didn’t work, obviously.

What I expect is working autocomplete in PyCharm 2016.3.2. Pre-annotation like this:

i: int
for i in range(5):
    pass

doesn’t help.

P.S. Pre-annotation works for PyCharm >= 2017.1


回答 0

根据PEP 526,这是不允许的:

另外,不能注释forwith 语句中使用的变量。可以像元组拆包一样提前注释它们

在循环之前对其进行注释:

i: int
for i in range(5):
    pass

PyCharm 2018.1及更高版本现在可以识别循环内变量的类型。较早的PyCharm版本不支持此功能。

According to PEP 526, this is not allowed:

In addition, one cannot annotate variables used in a for or with statement; they can be annotated ahead of time, in a similar manner to tuple unpacking

Annotate it before the loop:

i: int
for i in range(5):
    pass

PyCharm 2018.1 and up now recognizes the type of the variable inside the loop. This was not supported in older PyCharm versions.


回答 1

我不知道此解决方案是否与PEP兼容,或者仅仅是PyCharm的功能,但我使它像这样工作

for i in range(5): #type: int
  pass

我正在使用Pycharm Community Edition 2016.2.1

I don’t know if this solution is PEP compatible or just a feature of PyCharm but I made it work like this

for i in range(5): #type: int
  pass

and I’m using Pycharm Community Edition 2016.2.1


回答 2

这对我在PyCharm(使用Python 3.6)中的效果很好

for i in range(5):
    i: int = i
    pass

This works well for my in PyCharm (using Python 3.6)

for i in range(5):
    i: int = i
    pass

回答 3

这里的回答都没有用,只是说不能。甚至接受的答案也使用PEP 526文档中的语法,这不是有效的python语法。如果您尝试输入

x: int

您会看到这是一个语法错误。

这是一个有用的解决方法:

for __x in range(5):
    x = __x  # type: int
    print(x)

做您的工作x。PyCharm可以识别其类型,并且可以自动完成。

None of the responses here were useful, except to say that you can’t. Even the accepted answer uses syntax from the PEP 526 document, which isn’t valid python syntax. If you try to type in

x: int

You’ll see it’s a syntax error.

Here is a useful workaround:

for __x in range(5):
    x = __x  # type: int
    print(x)

Do your work with x. PyCharm recognizes its type, and autocomplete works.


ModuleNotFoundError:__main__不是软件包是什么意思?

问题:ModuleNotFoundError:__main__不是软件包是什么意思?

我正在尝试从控制台运行模块。我的目录结构是这样的:

我正在尝试使用以下命令p_03_using_bisection_search.pyproblem_set_02目录中运行模块:

$ python3 p_03_using_bisection_search.py

里面的代码p_03_using_bisection_search.py是:

__author__ = 'm'


from .p_02_paying_debt_off_in_a_year import compute_balance_after


def compute_bounds(balance: float,
                   annual_interest_rate: float) -> (float, float):

    # there is code here, but I have omitted it to save space
    pass


def compute_lowest_payment(balance: float,
                           annual_interest_rate: float) -> float:

    # there is code here, but I have omitted it to save space
    pass    

def main():
    balance = eval(input('Enter the initial balance: '))
    annual_interest_rate = eval(input('Enter the annual interest rate: '))

    lowest_payment = compute_lowest_payment(balance, annual_interest_rate)
    print('Lowest Payment: ' + str(lowest_payment))


if __name__ == '__main__':
    main()

我正在导入p_02_paying_debt_off_in_a_year.py其中代码是的函数:

__author__ = 'm'


def compute_balance(balance: float,
                    fixed_payment: float,
                    annual_interest_rate: float) -> float:

    # this is code that has been omitted
    pass


def compute_balance_after(balance: float,
                          fixed_payment: float,
                          annual_interest_rate: float,
                          months: int=12) -> float:

    # Omitted code
    pass


def compute_fixed_monthly_payment(balance: float,
                                  annual_interest_rate: float) -> float:

    # omitted code
    pass


def main():
    balance = eval(input('Enter the initial balance: '))
    annual_interest_rate = eval(
        input('Enter the annual interest rate as a decimal: '))
    lowest_payment = compute_fixed_monthly_payment(balance,
                                                   annual_interest_rate)
    print('Lowest Payment: ' + str(lowest_payment))


if __name__ == '__main__':
    main()

我收到以下错误:

ModuleNotFoundError: No module named '__main__.p_02_paying_debt_off_in_a_year'; '__main__' is not a package

我不知道如何解决这个问题。我尝试添加__init__.py文件,但是仍然无法正常工作。

I am trying to run a module from the console. The structure of my directory is this:

I am trying to run the module p_03_using_bisection_search.py, from the problem_set_02 directory using:

$ python3 p_03_using_bisection_search.py

The code inside p_03_using_bisection_search.pyis:

__author__ = 'm'


from .p_02_paying_debt_off_in_a_year import compute_balance_after


def compute_bounds(balance: float,
                   annual_interest_rate: float) -> (float, float):

    # there is code here, but I have omitted it to save space
    pass


def compute_lowest_payment(balance: float,
                           annual_interest_rate: float) -> float:

    # there is code here, but I have omitted it to save space
    pass    

def main():
    balance = eval(input('Enter the initial balance: '))
    annual_interest_rate = eval(input('Enter the annual interest rate: '))

    lowest_payment = compute_lowest_payment(balance, annual_interest_rate)
    print('Lowest Payment: ' + str(lowest_payment))


if __name__ == '__main__':
    main()

I am importing a function that is in p_02_paying_debt_off_in_a_year.py which code is:

__author__ = 'm'


def compute_balance(balance: float,
                    fixed_payment: float,
                    annual_interest_rate: float) -> float:

    # this is code that has been omitted
    pass


def compute_balance_after(balance: float,
                          fixed_payment: float,
                          annual_interest_rate: float,
                          months: int=12) -> float:

    # Omitted code
    pass


def compute_fixed_monthly_payment(balance: float,
                                  annual_interest_rate: float) -> float:

    # omitted code
    pass


def main():
    balance = eval(input('Enter the initial balance: '))
    annual_interest_rate = eval(
        input('Enter the annual interest rate as a decimal: '))
    lowest_payment = compute_fixed_monthly_payment(balance,
                                                   annual_interest_rate)
    print('Lowest Payment: ' + str(lowest_payment))


if __name__ == '__main__':
    main()

I am getting the following error:

ModuleNotFoundError: No module named '__main__.p_02_paying_debt_off_in_a_year'; '__main__' is not a package

I have no idea how to solve this issue. I have tried adding a __init__.py file, but it is still not working.


回答 0

只需删除相对导入的点,然后执行以下操作:

from p_02_paying_debt_off_in_a_year import compute_balance_after

Simply remove the dot for the relative import and do:

from p_02_paying_debt_off_in_a_year import compute_balance_after

回答 1

我和你有同样的问题。我认为问题是您在中使用了相对导入in-package import__init__.py您的目录中没有。因此,请按照以上摩西的回答进行导入。

我认为核心问题是在导入点时:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

它等效于:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

where __main__指您当前的模块p_03_using_bisection_search.py


简而言之,解释器不知道您的目录体系结构。

当解释器进入时p_03.py,脚本等于:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

并且p_03_using_bisection_search不包含任何名为的模块或实例p_02_paying_debt_off_in_a_year


因此,我想出了一个更干净的解决方案,而无需更改python环境的贵重物品(在查找请求在相对导入中的作用之后):

该目录的主要体系结构是:

main.py

setup.py

problem_set_02/

——__init__.py

——p01.py

——p02.py

——p03.py

然后写__init__.py

from .p_02_paying_debt_off_in_a_year import compute_balance_after

这里__main____init__,它究竟指的是模块problem_set_02

然后转到main.py

import problem_set_02

您也可以编写一个setup.py将特定模块添加到环境中。

I have the same issue as you did. I think the problem is that you used relative import in in-package import. There is no __init__.py in your directory. So just import as Moses answered above.

The core issue I think is when you import with a dot:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

It is equivalent to:

from __main__.p_02_paying_debt_off_in_a_year import compute_balance_after

where __main__ refers to your current module p_03_using_bisection_search.py.


Briefly, the interpreter does not know your directory architecture.

When the interpreter get in p_03.py, the script equals:

from p_03_using_bisection_search.p_02_paying_debt_off_in_a_year import compute_balance_after

and p_03_using_bisection_search does not contain any modules or instances called p_02_paying_debt_off_in_a_year.


So I came up with a cleaner solution without changing python environment valuables (after looking up how requests do in relative import):

The main architecture of the directory is:

main.py
setup.py
problem_set_02/
   __init__.py
   p01.py
   p02.py
   p03.py

Then write in __init__.py:

from .p_02_paying_debt_off_in_a_year import compute_balance_after

Here __main__ is __init__ , it exactly refers to the module problem_set_02.

Then go to main.py:

import problem_set_02

You can also write a setup.py to add specific module to the environment.


回答 2

尝试将其运行为:

python3 -m p_03_using_bisection_search

Try to run it as:

python3 -m p_03_using_bisection_search


回答 3

您好,请按照以下步骤操作,您将解决此问题。如果已创建目录和子目录,请按照以下步骤操作,请记住,所有目录必须必须 __init__.py将其识别为目录。

  1. import sys并运行sys.path,您将能够看到python搜索的所有路径。您必须能够看到当前的工作目录。

  2. 现在,按照以下命令导入要使用import使用的子目录和相应模块:import subdir.subdir.modulename as abc现在,您可以使用该模块中的方法。 屏幕截图相同的问题

如您在此屏幕快照中看到的,我有一个父目录和两个子目录,在第二个子目录下,我有module == CommonFunction,执行sys.path后您会看到右侧,我可以看到我的工作目录

If you have created directory and sub-directory, follow the steps below and please keep in mind all directory must have __init__.py to get it recognized as a directory.

  1. In your script, include import sys and sys.path, you will be able to see all the paths available to Python. You must be able to see your current working directory.

  2. Now import sub-directory and respective module that you want to use using: import subdir.subdir.modulename as abc and now you can use the methods in that module.

As an example, you can see in this screenshot I have one parent directory and two sub-directories and under second sub-directories I have the module CommonFunction. On the right my console shows that after execution of sys.path, I can see my working directory.


回答 4

删除点并在文件开头导入absolute_import

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after

Remove the dot and import absolute_import in the beginning of your file

from __future__ import absolute_import

from p_02_paying_debt_off_in_a_year import compute_balance_after

回答 5

只需使用.py文件所在的主文件夹的名称即可。

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after

Just use the name of the main folder which the .py file is in.

from problem_set_02.p_02_paying_debt_off_in_a_year import compute_balance_after

是否在Python 3.6+中订购了字典?

问题:是否在Python 3.6+中订购了字典?

与以前的版本不同,字典在Python 3.6中排序(至少在CPython实现下)。这似乎是一个重大更改,但只是文档中的一小段。它被描述为CPython实现细节而不是语言功能,但这也意味着将来可能会成为标准。

在保留元素顺序的同时,新的字典实现如何比旧的实现更好?

以下是文档中的文字:

dict()现在使用PyPy率先提出的“紧凑”表示形式。与Python 3.5相比,新dict()的内存使用量减少了20%至25%。PEP 468(在函数中保留** kwarg的顺序。)由此实现。此新实现的顺序保留方面被认为是实现细节,因此不应依赖(将来可能会更改,但是希望在更改语言规范之前,先在几个发行版中使用该新dict实现该语言,为所有当前和将来的Python实现强制要求保留顺序的语义;这还有助于保留与仍旧有效的随机迭代顺序的旧版本语言(例如Python 3.5)的向后兼容性。(由INADA Naoki在发行27350最初由Raymond Hettinger提出的想法。)

2017年12月更新:Python 3.7 保证dict保留插入顺序

Dictionaries are ordered in Python 3.6 (under the CPython implementation at least) unlike in previous incarnations. This seems like a substantial change, but it’s only a short paragraph in the documentation. It is described as a CPython implementation detail rather than a language feature, but also implies this may become standard in the future.

How does the new dictionary implementation perform better than the older one while preserving element order?

Here is the text from the documentation:

dict() now uses a “compact” representation pioneered by PyPy. The memory usage of the new dict() is between 20% and 25% smaller compared to Python 3.5. PEP 468 (Preserving the order of **kwargs in a function.) is implemented by this. The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon (this may change in the future, but it is desired to have this new dict implementation in the language for a few releases before changing the language spec to mandate order-preserving semantics for all current and future Python implementations; this also helps preserve backwards-compatibility with older versions of the language where random iteration order is still in effect, e.g. Python 3.5). (Contributed by INADA Naoki in issue 27350. Idea originally suggested by Raymond Hettinger.)

Update December 2017: dicts retaining insertion order is guaranteed for Python 3.7


回答 0

是否在Python 3.6+中订购了字典?

它们是插入顺序[1]。从Python 3.6开始,对于Python的CPython实现,字典会记住插入项目的顺序这在Python 3.6中被视为实现细节;你需要使用OrderedDict,如果你想多数民众赞成插入排序保证不同的Python的其它实现(与其他有序行为[1] )。

从Python 3.7开始,它不再是实现细节,而是成为一种语言功能。从GvR的py​​thon-dev消息中

做到这一点。裁定“裁定保留插入顺序”。谢谢!

这只是意味着您可以依靠它。如果其他Python实现希望成为Python 3.7的一致实现,则还必须提供插入顺序字典。


在保留元素顺序的同时,Python 3.6字典实现如何比旧的实现更好的性能[2]

本质上,通过保留两个数组

  • 第一个数组,按插入顺序dk_entries保存字典的条目(类型PyDictKeyEntry)。保留顺序是通过仅附加数组来实现的,在该数组中始终在末尾插入新项(插入顺序)。

  • 第二个dk_indices保留dk_entries数组的索引(即,指示中相应条目位置的值dk_entries)。该数组充当哈希表。对键进行哈希处理时,它会导致存储在其中的索引之一,dk_indices并且通过indexing获取相应的条目dk_entries。由于只有索引被保留,此数组的类型取决于字典的整体大小(范围从类型int8_t1字节)到int32_t/ int64_t4/ 8字节)上32/ 64位构建)

在以前的实现中,必须分配类型PyDictKeyEntry和大小的稀疏数组dk_size。不幸的是,由于性能原因,该阵列不允许2/3 * dk_size满载,这也导致了很多空白。(并且空白区域具有大小!)。PyDictKeyEntry

现在不是这种情况,因为仅存储了必需的条目(已插入的条目),并且保留了一个稀疏类型的数组intX_tX取决于dict的大小)2/3 * dk_size。空格从类型更改PyDictKeyEntryintX_t

因此,显然,创建一个类型PyDictKeyEntry稀疏的数组比存储ints 的稀疏数组需要更多的内存。

如果有兴趣,可以在Python-Dev上查看有关此功能的完整对话,这是一本好书。


在Raymond Hettinger提出的原始建议中,可以看到使用的数据结构的可视化效果,该可视化体现了该思想的要旨。

例如,字典:

d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}

当前存储为[keyhash,key,value]:

entries = [['--', '--', '--'],
           [-8522787127447073495, 'barry', 'green'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           [-9092791511155847987, 'timmy', 'red'],
           ['--', '--', '--'],
           [-6480567542315338377, 'guido', 'blue']]

相反,数据应按以下方式组织:

indices =  [None, 1, None, None, None, 0, None, 2]
entries =  [[-9092791511155847987, 'timmy', 'red'],
            [-8522787127447073495, 'barry', 'green'],
            [-6480567542315338377, 'guido', 'blue']]

正如您现在可以从视觉上看到的那样,在原始建议中,很多空间实际上是空的,以减少冲突并加快查找速度。使用新方法,可以通过将稀疏移动到真正需要的索引中来减少所需的内存。


[1]:我说“插入有序”而不是“有序”,因为在存在OrderedDict的情况下,“有序”暗示了dict对象不提供的其他行为。OrderedDicts是可逆的,提供顺序敏感的方法,并且主要是,提供一个订单sensive相等测试(==!=)。dict目前不提供任何这些行为/方法。


[2]:新的字典实现通过更紧凑的设计而在内存方面表现更好;这是这里的主要好处。在速度方面,差异并不那么明显,在某些地方,新的dict可能会引入轻微的回归(例如,关键查找),而在其他地方(会想到迭代和调整大小),应该会提高性能。

总体而言,由于引入的紧凑性,字典的性能(尤其是在现实生活中)得以提高。

Are dictionaries ordered in Python 3.6+?

They are insertion ordered[1]. As of Python 3.6, for the CPython implementation of Python, dictionaries remember the order of items inserted. This is considered an implementation detail in Python 3.6; you need to use OrderedDict if you want insertion ordering that’s guaranteed across other implementations of Python (and other ordered behavior[1]).

As of Python 3.7, this is no longer an implementation detail and instead becomes a language feature. From a python-dev message by GvR:

Make it so. “Dict keeps insertion order” is the ruling. Thanks!

This simply means that you can depend on it. Other implementations of Python must also offer an insertion ordered dictionary if they wish to be a conforming implementation of Python 3.7.


How does the Python 3.6 dictionary implementation perform better[2] than the older one while preserving element order?

Essentially, by keeping two arrays.

  • The first array, dk_entries, holds the entries (of type PyDictKeyEntry) for the dictionary in the order that they were inserted. Preserving order is achieved by this being an append only array where new items are always inserted at the end (insertion order).

  • The second, dk_indices, holds the indices for the dk_entries array (that is, values that indicate the position of the corresponding entry in dk_entries). This array acts as the hash table. When a key is hashed it leads to one of the indices stored in dk_indices and the corresponding entry is fetched by indexing dk_entries. Since only indices are kept, the type of this array depends on the overall size of the dictionary (ranging from type int8_t(1 byte) to int32_t/int64_t (4/8 bytes) on 32/64 bit builds)

In the previous implementation, a sparse array of type PyDictKeyEntry and size dk_size had to be allocated; unfortunately, it also resulted in a lot of empty space since that array was not allowed to be more than 2/3 * dk_size full for performance reasons. (and the empty space still had PyDictKeyEntry size!).

This is not the case now since only the required entries are stored (those that have been inserted) and a sparse array of type intX_t (X depending on dict size) 2/3 * dk_sizes full is kept. The empty space changed from type PyDictKeyEntry to intX_t.

So, obviously, creating a sparse array of type PyDictKeyEntry is much more memory demanding than a sparse array for storing ints.

You can see the full conversation on Python-Dev regarding this feature if interested, it is a good read.


In the original proposal made by Raymond Hettinger, a visualization of the data structures used can be seen which captures the gist of the idea.

For example, the dictionary:

d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}

is currently stored as [keyhash, key, value]:

entries = [['--', '--', '--'],
           [-8522787127447073495, 'barry', 'green'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           ['--', '--', '--'],
           [-9092791511155847987, 'timmy', 'red'],
           ['--', '--', '--'],
           [-6480567542315338377, 'guido', 'blue']]

Instead, the data should be organized as follows:

indices =  [None, 1, None, None, None, 0, None, 2]
entries =  [[-9092791511155847987, 'timmy', 'red'],
            [-8522787127447073495, 'barry', 'green'],
            [-6480567542315338377, 'guido', 'blue']]

As you can visually now see, in the original proposal, a lot of space is essentially empty to reduce collisions and make look-ups faster. With the new approach, you reduce the memory required by moving the sparseness where it’s really required, in the indices.


[1]: I say “insertion ordered” and not “ordered” since, with the existence of OrderedDict, “ordered” suggests further behavior that the dict object doesn’t provide. OrderedDicts are reversible, provide order sensitive methods and, mainly, provide an order-sensive equality tests (==, !=). dicts currently don’t offer any of those behaviors/methods.


[2]: The new dictionary implementations performs better memory wise by being designed more compactly; that’s the main benefit here. Speed wise, the difference isn’t so drastic, there’s places where the new dict might introduce slight regressions (key-lookups, for example) while in others (iteration and resizing come to mind) a performance boost should be present.

Overall, the performance of the dictionary, especially in real-life situations, improves due to the compactness introduced.


回答 1

以下是回答最初的第一个问题:

我应该在Python 3.6中使用dict还是OrderedDict在Python 3.6中使用?

我认为文档中的这句话实际上足以回答您的问题

此新实现的顺序保留方面被视为实现细节,不应依赖于此

dict并不明确表示它是有序集合,因此,如果您要保持一致并且不依赖于新实现的副作用,则应坚持使用OrderedDict

使您的代码成为未来的证明:)

有关于辩论在这里

编辑:Python 3.7将保留此功能, 请参阅

Below is answering the original first question:

Should I use dict or OrderedDict in Python 3.6?

I think this sentence from the documentation is actually enough to answer your question

The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon

dict is not explicitly meant to be an ordered collection, so if you want to stay consistent and not rely on a side effect of the new implementation you should stick with OrderedDict.

Make your code future proof :)

There’s a debate about that here.

EDIT: Python 3.7 will keep this as a feature see


回答 2

更新:Guido van Rossum 在邮件列表宣布,从 Python 3.7开始dict,所有Python实现中必须保留插入顺序。

Update: Guido van Rossum announced on the mailing list that as of Python 3.7 dicts in all Python implementations must preserve insertion order.


回答 3

我想添加到上面的讨论中,但没有评论的声誉。

Python 3.8尚未发布,但它甚至将包含reversed()字典上的函数(消除了的另一个区别OrderedDict。)。

现在可以使用reversed()以反向插入顺序迭代Dict和dictviews。(由RémiLapeyre在bpo-33462中贡献。) 查看python 3.8的新增功能

我没有提到相等运算符或的其他功能,OrderedDict因此它们仍然不完全相同。

I wanted to add to the discussion above but don’t have the reputation to comment.

Python 3.8 is not quite released yet, but it will even include the reversed() function on dictionaries (removing another difference from OrderedDict.

Dict and dictviews are now iterable in reversed insertion order using reversed(). (Contributed by Rémi Lapeyre in bpo-33462.) See what’s new in python 3.8

I don’t see any mention of the equality operator or other features of OrderedDict so they are still not entirely the same.