标签归档:python-2.7

如何编写Python模块/软件包?

问题:如何编写Python模块/软件包?

我一直在为工作中的简单任务制作Python脚本,从来没有真正打扰过将它们打包供其他人使用。现在,我被分配为REST API制作Python包装器。我对如何开始一无所知,我需要帮助。

我有的:

(只想尽可能地具体一点)我已经准备好virtualenv,它也位于github上,还存在用于python的.gitignore文件,以及用于与REST API交互的请求库。而已。

这是当前目录树

.
├── bin
   └── /the usual stuff/
├── include
   └── /the usual stuff/
├── lib
   └── python2.7
       └── /the usual stuff/
├── local
   └── /the usual stuff/
└── README.md

27 directories, 280 files

我什至不知道将.py文件放在哪里。

我想做的是:

使用“ pip install …”制作可安装的python模块

如果可能的话,我需要一个逐步的编写Python模块的逐步过程。

I’ve been making Python scripts for simple tasks at work and never really bothered packaging them for others to use. Now I have been assigned to make a Python wrapper for a REST API. I have absolutely no idea on how to start and I need help.

What I have:

(Just want to be specific as possible) I have the virtualenv ready, it’s also up in github, the .gitignore file for python is there as well, plus, the requests library for interacting with the REST API. That’s it.

Here’s the current directory tree

.
├── bin
│   └── /the usual stuff/
├── include
│   └── /the usual stuff/
├── lib
│   └── python2.7
│       └── /the usual stuff/
├── local
│   └── /the usual stuff/
└── README.md

27 directories, 280 files

I don’t even know where to put the .py files, if I ever make one.

What I wanted to do:

Make a python module install-able with “pip install …”

If possible, I want a general step by step process on writing Python modules.


回答 0

模块是包含Python定义和语句的文件。文件名是带有后缀的模块名称.py

创建hello.py然后编写以下函数作为其内容:

def helloworld():
   print "hello"

然后,您可以导入hello

>>> import hello
>>> hello.helloworld()
'hello'
>>>

要对许多.py文件进行分组,请将它们放在文件夹中。带有的任何文件夹__init__.py都被python视为模块,您可以将其称为包

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

您可以按照通常的方式在模块上使用import语句。

有关更多信息,请参见6.4。包

A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py

create hello.py then write the following function as its content:

def helloworld():
   print "hello"

Then you can import hello:

>>> import hello
>>> hello.helloworld()
'hello'
>>>

To group many .py files put them in a folder. Any folder with an __init__.py is considered a module by python and you can call them a package

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

You can go about with the import statement on your module the usual way.

For more information, see 6.4. Packages.


回答 1

Python 3-更新于2015年11月18日

认为已接受的答案很有用,但希望根据我自己的经验在几个方面进行扩展,以使他人受益。

模块:模块是包含Python定义和语句的文件。文件名是模块名称,后缀.py。

模块示例:假设我们在当前目录中只有一个python脚本,在这里我将其称为mymodule.py

文件mymodule.py包含以下代码:

def myfunc():
    print("Hello!")

如果我们从当前目录运行python3解释器,则可以通过以下不同方式导入和运行函数myfunc(通常,您只需选择以下一种):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

好的,这很容易。

现在假设您需要将该模块放入其自己的专用文件夹中以提供模块命名空间,而不是仅从当前工作目录中临时运行它。这是值得解释软件包概念的地方。

:包是通过使用“点分模块名称”来构造Python模块命名空间的一种方式。例如,模块名称AB在名为A的包中指定了一个名为B的子模块。就像使用模块使不同模块的作者免于担心彼此的全局变量名一样,使用带点划线的模块名称也节省了作者诸如NumPy或Python Imaging Library之类的多模块软件包,而不必担心彼此的模块名称。

包示例:现在假设我们具有以下文件夹和文件。在这里,mymodule.py与以前相同,并且__init__.py是一个空文件:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

__init__.py文件是使Python将目录视为包含包的必需文件。有关更多信息,请参见稍后提供的模块文档链接。

我们当前的工作目录位于名为mypackage的普通文件夹之上的一级

$ ls
mypackage

如果现在运行python3解释器,则可以通过以下不同方式导入并运行包含所需函数myfunc的模块mymodule.py(通常,您只需选择以下一种):

>>> import mypackage
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> import mypackage.mymodule
>>> mypackage.mymodule.myfunc()
Hello!
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mypackage.mymodule import myfunc
>>> myfunc()
Hello!
>>> from mypackage.mymodule import *
>>> myfunc()
Hello!

假设使用Python 3,以下位置提供了出色的文档:模块

关于程序包和模块的命名约定,PEP-0008中给出了通用准则-请参阅程序包和模块名称

模块应使用简短的全小写名称。如果模块名称可以提高可读性,则可以在模块名称中使用下划线。尽管不鼓励使用下划线,但Python软件包也应使用短小写全名。

Python 3 – UPDATED 18th November 2015

Found the accepted answer useful, yet wished to expand on several points for the benefit of others based on my own experiences.

Module: A module is a file containing Python definitions and statements. The file name is the module name with the suffix .py appended.

Module Example: Assume we have a single python script in the current directory, here I am calling it mymodule.py

The file mymodule.py contains the following code:

def myfunc():
    print("Hello!")

If we run the python3 interpreter from the current directory, we can import and run the function myfunc in the following different ways (you would typically just choose one of the following):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

Ok, so that was easy enough.

Now assume you have the need to put this module into its own dedicated folder to provide a module namespace, instead of just running it ad-hoc from the current working directory. This is where it is worth explaining the concept of a package.

Package: Packages are a way of structuring Python’s module namespace by using “dotted module names”. For example, the module name A.B designates a submodule named B in a package named A. Just like the use of modules saves the authors of different modules from having to worry about each other’s global variable names, the use of dotted module names saves the authors of multi-module packages like NumPy or the Python Imaging Library from having to worry about each other’s module names.

Package Example: Let’s now assume we have the following folder and files. Here, mymodule.py is identical to before, and __init__.py is an empty file:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

The __init__.py files are required to make Python treat the directories as containing packages. For further information, please see the Modules documentation link provided later on.

Our current working directory is one level above the ordinary folder called mypackage

$ ls
mypackage

If we run the python3 interpreter now, we can import and run the module mymodule.py containing the required function myfunc in the following different ways (you would typically just choose one of the following):

>>> import mypackage
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> import mypackage.mymodule
>>> mypackage.mymodule.myfunc()
Hello!
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mypackage.mymodule import myfunc
>>> myfunc()
Hello!
>>> from mypackage.mymodule import *
>>> myfunc()
Hello!

Assuming Python 3, there is excellent documentation at: Modules

In terms of naming conventions for packages and modules, the general guidelines are given in PEP-0008 – please see Package and Module Names

Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.


回答 2

由于尚无人讨论过OP的这个问题:

我想做的是:

使用“ pip install …”制作可安装的python模块

这是一个绝对的最小示例,显示了使用setuptools和准备软件包并将其上传到PyPI的基本步骤twine

这绝不能代替阅读至少本教程,它比这个非常基本的示例所涵盖的内容要多得多。

在这里,其他答案已经涵盖了创建包本身,因此,让我们假设我们已经覆盖了这一步,并且我们的项目结构如下:

.
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

为了setuptools用于打包,我们需要添加一个文件setup.py,该文件进入我们项目的根文件夹:

.
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

至少,我们为包指定元数据,setup.py如下所示:

from setuptools import setup

setup(
    name='hellostackoverflow',
    version='0.0.1',
    description='a pip-installable package example',
    license='MIT',
    packages=['hellostackoverflow'],
    author='Benjamin Gerfelder',
    author_email='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

设置好之后license='MIT',我们在项目中添加了一个副本,LICENCE.txt在reStructuredText中添加了一个自述文件,如下所示README.rst

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

此时,我们准备开始使用进行打包setuptools,如果尚未安装,可以使用以下命令进行安装pip

pip install setuptools

为了做到这一点并source distribution在项目的根文件夹中创建一个,我们setup.py从命令行调用我们,指定我们想要的sdist

python setup.py sdist

这将创建我们的分发程序包和egg-info,并导致这样的文件夹结构,我们的程序包位于dist

.
├── dist/
├── hellostackoverflow.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

至此,我们有了一个可以使用安装的软件包pip,因此从我们的项目根目录开始(假设您具有本示例中的所有命名):

pip install ./dist/hellostackoverflow-0.0.1.tar.gz

如果一切顺利,我们现在可以打开一个Python解释器,我想在项目目录之外的某个地方说以避免任何混淆,然后尝试使用新的闪亮包:

Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hellostackoverflow import hellostackoverflow
>>> hellostackoverflow.greeting()
'Hello Stack Overflow!'

现在,我们已经确认该软件包已安装并且可以正常工作,我们可以将其上传到PyPI。

由于我们不想用我们的实验污染实时存储库,因此我们为测试存储库创建一个帐户,并twine为上载过程进行安装:

pip install twine

现在我们快到了,创建帐户后,我们只需要告诉twine我们上传软件包,它将要求我们提供凭据并将软件包上传到指定的存储库:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

现在,我们可以在PyPI测试库上登录我们的帐户,惊叹我们刚上传的软件包一段时间,然后使用pip以下代码进行抓取:

pip install --index-url https://test.pypi.org/simple/ hellostackoverflow

我们可以看到,基本过程不是很复杂。正如我之前所说的,它所包含的内容远不止本文所述,因此请继续阅读本教程以获取更深入的说明。

Since nobody did cover this question of the OP yet:

What I wanted to do:

Make a python module install-able with “pip install …”

Here is an absolute minimal example, showing the basic steps of preparing and uploading your package to PyPI using setuptools and twine.

This is by no means a substitute for reading at least the tutorial, there is much more to it than covered in this very basic example.

Creating the package itself is already covered by other answers here, so let us assume we have that step covered and our project structure like this:

.
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

In order to use setuptools for packaging, we need to add a file setup.py, this goes into the root folder of our project:

.
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

At the minimum, we specify the metadata for our package, our setup.py would look like this:

from setuptools import setup

setup(
    name='hellostackoverflow',
    version='0.0.1',
    description='a pip-installable package example',
    license='MIT',
    packages=['hellostackoverflow'],
    author='Benjamin Gerfelder',
    author_email='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

Since we have set license='MIT', we include a copy in our project as LICENCE.txt, alongside a readme file in reStructuredText as README.rst:

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

At this point, we are ready to go to start packaging using setuptools, if we do not have it already installed, we can install it with pip:

pip install setuptools

In order to do that and create a source distribution, at our project root folder we call our setup.py from the command line, specifying we want sdist:

python setup.py sdist

This will create our distribution package and egg-info, and result in a folder structure like this, with our package in dist:

.
├── dist/
├── hellostackoverflow.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

At this point, we have a package we can install using pip, so from our project root (assuming you have all the naming like in this example):

pip install ./dist/hellostackoverflow-0.0.1.tar.gz

If all goes well, we can now open a Python interpreter, I would say somewhere outside our project directory to avoid any confusion, and try to use our shiny new package:

Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hellostackoverflow import hellostackoverflow
>>> hellostackoverflow.greeting()
'Hello Stack Overflow!'

Now that we have confirmed the package installs and works, we can upload it to PyPI.

Since we do not want to pollute the live repository with our experiments, we create an account for the testing repository, and install twine for the upload process:

pip install twine

Now we’re almost there, with our account created we simply tell twine to upload our package, it will ask for our credentials and upload our package to the specified repository:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

We can now log into our account on the PyPI test repository and marvel at our freshly uploaded package for a while, and then grab it using pip:

pip install --index-url https://test.pypi.org/simple/ hellostackoverflow

As we can see, the basic process is not very complicated. As I said earlier, there is a lot more to it than covered here, so go ahead and read the tutorial for more in-depth explanation.


回答 3

定义所选命令后,只需将保存的文件拖放到python程序文件中的Lib文件夹中即可。

>>> import mymodule 
>>> mymodule.myfunc()

Once you have defined your chosen commands, you can simply drag and drop the saved file into the Lib folder in your python program files.

>>> import mymodule 
>>> mymodule.myfunc()

回答 4

制作一个名为“ hello.py”的文件

如果您使用的是Python 2.x

def func():
    print "Hello"

如果您使用的是Python 3.x

def func():
    print("Hello")

运行文件。然后,您可以尝试以下操作:

>>> import hello
>>> hello.func()
Hello

如果您想稍微努力一点,可以使用以下方法:

如果您使用的是Python 2.x

def say(text):
    print text

如果您使用的是Python 3.x

def say(text):
    print(text)

看到定义旁边括号中的一个吗?那很重要。您可以在定义中使用它。

文本-​​当您希望程序说出想要的内容时可以使用它。根据其名称,它是文本。希望您知道文本的含义。它的意思是“单词”或“句子”。

运行文件。然后,如果您使用的是Python 3.x,则可以尝试以下操作:

>>> import hello
>>> hello.say("hi")
hi
>>> from hello import say
>>> say("test")
test

对于Python 2.x-我猜与Python 3相同吗?不知道。如果我在Python 2.x上犯了一个错误,请纠正我(我知道Python 2,但是我与Python 3一起使用)

Make a file named “hello.py”

If you are using Python 2.x

def func():
    print "Hello"

If you are using Python 3.x

def func():
    print("Hello")

Run the file. Then, you can try the following:

>>> import hello
>>> hello.func()
Hello

If you want a little bit hard, you can use the following:

If you are using Python 2.x

def say(text):
    print text

If you are using Python 3.x

def say(text):
    print(text)

See the one on the parenthesis beside the define? That is important. It is the one that you can use within the define.

Text – You can use it when you want the program to say what you want. According to its name, it is text. I hope you know what text means. It means “words” or “sentences”.

Run the file. Then, you can try the following if you are using Python 3.x:

>>> import hello
>>> hello.say("hi")
hi
>>> from hello import say
>>> say("test")
test

For Python 2.x – I guess same thing with Python 3? No idea. Correct me if I made a mistake on Python 2.x (I know Python 2 but I am used with Python 3)


回答 5

我创建了一个项目,以轻松地从头开始创建项目框架https://github.com/MacHu-GWU/pygitrepo-project

假设您可以创建一个测试项目learn_creating_py_package

您可以了解具有不同用途的组件,例如

  • 创建virtualenv
  • 自行安装
  • 运行单元测试
  • 运行代码覆盖率
  • 建立文件
  • 部署文件
  • 在不同的python版本中运行unittest
  • 部署到PYPI

使用的好处pygitrepo是,这些繁琐的自动创建本身和适应你package_nameproject_namegithub_accountdocument host servicewindows or macos or linux

这是学习像pro一样开发python项目的好地方。

希望这会有所帮助。

谢谢。

I created a project to easily initiate a project skeleton from scratch. https://github.com/MacHu-GWU/pygitrepo-project.

And you can create a test project, let’s say, learn_creating_py_package.

You can learn what component you should have for different purpose like:

  • create virtualenv
  • install itself
  • run unittest
  • run code coverage
  • build document
  • deploy document
  • run unittest in different python version
  • deploy to PYPI

The advantage of using pygitrepo is that those tedious are automatically created itself and adapt your package_name, project_name, github_account, document host service, windows or macos or linux.

It is a good place to learn develop a python project like a pro.

Hope this could help.

Thank you.


如何在Python字符串中有选择地转义百分比(%)?

问题:如何在Python字符串中有选择地转义百分比(%)?

我有以下代码

test = "have it break."
selectiveEscape = "Print percent % in sentence and not %s" % test

print(selectiveEscape)

我想获得输出:

Print percent % in sentence and not have it break.

实际发生的情况:

    selectiveEscape = "Use percent % in sentence and not %s" % test
TypeError: %d format: a number is required, not str

I have the following code

test = "have it break."
selectiveEscape = "Print percent % in sentence and not %s" % test

print(selectiveEscape)

I would like to get the output:

Print percent % in sentence and not have it break.

What actually happens:

    selectiveEscape = "Use percent % in sentence and not %s" % test
TypeError: %d format: a number is required, not str

回答 0

>>> test = "have it break."
>>> selectiveEscape = "Print percent %% in sentence and not %s" % test
>>> print selectiveEscape
Print percent % in sentence and not have it break.
>>> test = "have it break."
>>> selectiveEscape = "Print percent %% in sentence and not %s" % test
>>> print selectiveEscape
Print percent % in sentence and not have it break.

回答 1

另外,从Python 2.6开始,您可以使用新的字符串格式(如PEP 3101中所述):

'Print percent % in sentence and not {0}'.format(test)

当您的弦变得越来越复杂时,这尤其方便。

Alternatively, as of Python 2.6, you can use new string formatting (described in PEP 3101):

'Print percent % in sentence and not {0}'.format(test)

which is especially handy as your strings get more complicated.


回答 2

尝试使用%%打印%符号。

try using %% to print % sign .


回答 3

您不能选择性地转义%,因为%根据以下字符,它总是具有特殊的含义。

在Python 文档中,该部分第二个表格的底部指出:

'%'        No argument is converted, results in a '%' character in the result.

因此,您应该使用:

selectiveEscape = "Print percent %% in sentence and not %s" % (test, )

(请注意,将元组的显式更改作为的参数%

在不了解上述情况的情况下,我会这样做:

selectiveEscape = "Print percent %s in sentence and not %s" % ('%', test)

显然你已经有了知识。

You can’t selectively escape %, as % always has a special meaning depending on the following character.

In the documentation of Python, at the bottem of the second table in that section, it states:

'%'        No argument is converted, results in a '%' character in the result.

Therefore you should use:

selectiveEscape = "Print percent %% in sentence and not %s" % (test, )

(please note the expicit change to tuple as argument to %)

Without knowing about the above, I would have done:

selectiveEscape = "Print percent %s in sentence and not %s" % ('%', test)

with the knowledge you obviously already had.


回答 4

如果从文件中读取了格式模板,并且不能确保内容将百分号加倍,则可能必须检测百分号并以编程方式确定它是否是占位符的开始。然后,解析器还应该识别类似%d(以及可以使用的其他字母)之类的序列,也应如此%(xxx)s

使用新格式可以观察到类似的问题-文本可以包含花括号。

If the formatting template was read from a file, and you cannot ensure the content doubles the percent sign, then you probably have to detect the percent character and decide programmatically whether it is the start of a placeholder or not. Then the parser should also recognize sequences like %d (and other letters that can be used), but also %(xxx)s etc.

Similar problem can be observed with the new formats — the text can contain curly braces.


回答 5

如果您使用的是Python 3.6或更高版本,则可以使用f-string

>>> test = "have it break."
>>> selectiveEscape = f"Print percent % in sentence and not {test}"
>>> print(selectiveEscape)
... Print percent % in sentence and not have it break.

If you are using Python 3.6 or newer, you can use f-string:

>>> test = "have it break."
>>> selectiveEscape = f"Print percent % in sentence and not {test}"
>>> print(selectiveEscape)
... Print percent % in sentence and not have it break.

回答 6

我尝试了不同的方法来打印子图标题,看看它们是如何工作的。当我使用乳胶时,情况有所不同。

在典型情况下,它适用于’%%’和’string’+’%’。

如果您使用Latex,则可以使用’string’+’\%’

因此,在典型情况下:

import matplotlib.pyplot as plt
fig,ax = plt.subplots(4,1)
float_number = 4.17
ax[0].set_title('Total: (%1.2f' %float_number + '\%)')
ax[1].set_title('Total: (%1.2f%%)' %float_number)
ax[2].set_title('Total: (%1.2f' %float_number + '%%)')
ax[3].set_title('Total: (%1.2f' %float_number + '%)')

带有%的标题示例

如果我们使用乳胶:

import matplotlib.pyplot as plt
import matplotlib
font = {'family' : 'normal',
        'weight' : 'bold',
        'size'   : 12}
matplotlib.rc('font', **font)
matplotlib.rcParams['text.usetex'] = True
matplotlib.rcParams['text.latex.unicode'] = True
fig,ax = plt.subplots(4,1)
float_number = 4.17
#ax[0].set_title('Total: (%1.2f\%)' %float_number) This makes python crash
ax[1].set_title('Total: (%1.2f%%)' %float_number)
ax[2].set_title('Total: (%1.2f' %float_number + '%%)')
ax[3].set_title('Total: (%1.2f' %float_number + '\%)')

我们得到这样的结果: 具有%和乳胶的标题示例

I have tried different methods to print a subplot title, look how they work. It’s different when i use Latex.

It works with ‘%%’ and ‘string’+’%’ in a typical case.

If you use Latex it worked using ‘string’+’\%’

So in a typical case:

import matplotlib.pyplot as plt
fig,ax = plt.subplots(4,1)
float_number = 4.17
ax[0].set_title('Total: (%1.2f' %float_number + '\%)')
ax[1].set_title('Total: (%1.2f%%)' %float_number)
ax[2].set_title('Total: (%1.2f' %float_number + '%%)')
ax[3].set_title('Total: (%1.2f' %float_number + '%)')

Title examples with %

If we use latex:

import matplotlib.pyplot as plt
import matplotlib
font = {'family' : 'normal',
        'weight' : 'bold',
        'size'   : 12}
matplotlib.rc('font', **font)
matplotlib.rcParams['text.usetex'] = True
matplotlib.rcParams['text.latex.unicode'] = True
fig,ax = plt.subplots(4,1)
float_number = 4.17
#ax[0].set_title('Total: (%1.2f\%)' %float_number) This makes python crash
ax[1].set_title('Total: (%1.2f%%)' %float_number)
ax[2].set_title('Total: (%1.2f' %float_number + '%%)')
ax[3].set_title('Total: (%1.2f' %float_number + '\%)')

We get this: Title example with % and latex


用pip安装PIL

问题:用pip安装PIL

我正在尝试使用以下命令安装PIL(Python Imaging Library):

sudo pip install pil

但我收到以下消息:

Downloading/unpacking PIL
  You are installing a potentially insecure and unverifiable file. Future versions of pip will default to disallowing insecure files.
  Downloading PIL-1.1.7.tar.gz (506kB): 506kB downloaded
  Running setup.py egg_info for package PIL
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py

Installing collected packages: PIL
  Running setup.py install for PIL
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    --- using frameworks at /System/Library/Frameworks
    building '_imaging' extension
    clang -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch x86_64 -pipe -IlibImaging -I/System/Library/Frameworks/Python.framework/Versions/2.7/include -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c _imaging.c -o build/temp.macosx-10.8-intel-2.7/_imaging.o
    unable to execute clang: No such file or directory
    error: command 'clang' failed with exit status 1
    Complete output from command /usr/bin/python -c "import setuptools;__file__='/private/tmp/pip_build_root/PIL/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-AYrxVD-record/install-record.txt --single-version-externally-managed:
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py

running install

running build

.
.
.
.

copying PIL/XVThumbImagePlugin.py -> build/lib.macosx-10.8-intel-2.7

running build_ext

--- using frameworks at /System/Library/Frameworks

building '_imaging' extension

creating build/temp.macosx-10.8-intel-2.7

creating build/temp.macosx-10.8-intel-2.7/libImaging

clang -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch x86_64 -pipe -IlibImaging -I/System/Library/Frameworks/Python.framework/Versions/2.7/include -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c _imaging.c -o build/temp.macosx-10.8-intel-2.7/_imaging.o

unable to execute clang: No such file or directory

error: command 'clang' failed with exit status 1

----------------------------------------
Cleaning up

您能帮我安装PIL吗?

I am trying to install PIL (the Python Imaging Library) using the command:

sudo pip install pil

but I get the following message:

Downloading/unpacking PIL
  You are installing a potentially insecure and unverifiable file. Future versions of pip will default to disallowing insecure files.
  Downloading PIL-1.1.7.tar.gz (506kB): 506kB downloaded
  Running setup.py egg_info for package PIL
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py

Installing collected packages: PIL
  Running setup.py install for PIL
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    --- using frameworks at /System/Library/Frameworks
    building '_imaging' extension
    clang -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch x86_64 -pipe -IlibImaging -I/System/Library/Frameworks/Python.framework/Versions/2.7/include -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c _imaging.c -o build/temp.macosx-10.8-intel-2.7/_imaging.o
    unable to execute clang: No such file or directory
    error: command 'clang' failed with exit status 1
    Complete output from command /usr/bin/python -c "import setuptools;__file__='/private/tmp/pip_build_root/PIL/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-AYrxVD-record/install-record.txt --single-version-externally-managed:
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py

running install

running build

.
.
.
.

copying PIL/XVThumbImagePlugin.py -> build/lib.macosx-10.8-intel-2.7

running build_ext

--- using frameworks at /System/Library/Frameworks

building '_imaging' extension

creating build/temp.macosx-10.8-intel-2.7

creating build/temp.macosx-10.8-intel-2.7/libImaging

clang -fno-strict-aliasing -fno-common -dynamic -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -mno-fused-madd -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch i386 -arch x86_64 -pipe -IlibImaging -I/System/Library/Frameworks/Python.framework/Versions/2.7/include -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c _imaging.c -o build/temp.macosx-10.8-intel-2.7/_imaging.o

unable to execute clang: No such file or directory

error: command 'clang' failed with exit status 1

----------------------------------------
Cleaning up…

Could you please help me to install PIL??


回答 0

  1. 如上所述安装Xcode和Xcode命令行工具。
  2. 请改用Pillow,因为PIL基本已失效。枕头是PIL的保养品。

https://pypi.python.org/pypi/Pillow/2.2.1

pip install Pillow

如果您同时安装了两个Python,并且想为Python3安装此代码,请执行以下操作:

python3 -m pip install Pillow
  1. Install Xcode and Xcode Command Line Tools as mentioned.
  2. Use Pillow instead, as PIL is basically dead. Pillow is a maintained fork of PIL.

https://pypi.python.org/pypi/Pillow/2.2.1

pip install Pillow

If you have both Pythons installed and want to install this for Python3:

python3 -m pip install Pillow

回答 1

这对我有用:

apt-get install python-dev
apt-get install libjpeg-dev
apt-get install libjpeg8-dev
apt-get install libpng3
apt-get install libfreetype6-dev
ln -s /usr/lib/i386-linux-gnu/libfreetype.so /usr/lib
ln -s /usr/lib/i386-linux-gnu/libjpeg.so /usr/lib
ln -s /usr/lib/i386-linux-gnu/libz.so /usr/lib

pip install PIL  --allow-unverified PIL --allow-all-external

This works for me:

apt-get install python-dev
apt-get install libjpeg-dev
apt-get install libjpeg8-dev
apt-get install libpng3
apt-get install libfreetype6-dev
ln -s /usr/lib/i386-linux-gnu/libfreetype.so /usr/lib
ln -s /usr/lib/i386-linux-gnu/libjpeg.so /usr/lib
ln -s /usr/lib/i386-linux-gnu/libz.so /usr/lib

pip install PIL  --allow-unverified PIL --allow-all-external

回答 2

使用apt install非常简单,使用此命令即可完成

sudo apt-get install python-PIL

要么

sudo pip install pillow

要么

sudo easy_install pillow

It is very simple using apt install use this command to get it done

sudo apt-get install python-PIL

or

sudo pip install pillow

or

sudo easy_install pillow

回答 3

在Mac OS X上,使用以下命令:

sudo pip install https://effbot.org/media/downloads/Imaging-1.1.7.tar.gz

On Mac OS X, use this command:

sudo pip install https://effbot.org/media/downloads/Imaging-1.1.7.tar.gz

回答 4

您应该描述安装在这里

pip install image

You should install as described here:

pip install image

回答 5

我从这里的讨论中得到了答案:

我试过了

pip install --no-index -f http://dist.plone.org/thirdparty/ -U PIL

而且有效。

I got the answer from a discussion here:

I tried

pip install --no-index -f http://dist.plone.org/thirdparty/ -U PIL

and it worked.


回答 6

安装

pip install Pillow

然后,只需导入文件,例如

from PIL import Image

我正在使用Windows。它为我工作。

注意

Pillow是Python Imaging Library的功能替代品。要使用Pillow运行现有的PIL兼容代码,需要对其进行修改以从PIL命名空间而不是全局命名空间导入Imaging模块。

即更改:

import Image

至:

from PIL import Image

https://pypi.org/project/枕头/2.2.1/

Install

pip install Pillow

Then, Just import in your file like,

from PIL import Image

I am using windows. It is working for me.

NOTE:

Pillow is a functional drop-in replacement for the Python Imaging Library. To run your existing PIL-compatible code with Pillow, it needs to be modified to import the Imaging module from the PIL namespace instead of the global namespace.

i.e. change:

import Image

to:

from PIL import Image

https://pypi.org/project/Pillow/2.2.1/


回答 7

我认为您在Mac上。请参阅如何在Mac OS X 10.7.2 Lion上安装PIL

如果使用[homebrew] [],则可以使用just安装PIL brew install pil。然后,您可能需要将安装目录($(brew --prefix)/lib/python2.7/site-packages)添加到PYTHONPATH中,或者将PIL目录本身的位置添加到PIL.pth任何site-packages目录中名为file的文件中,内容如下:

/usr/local/lib/python2.7/site-packages/PIL

(假设brew --prefix/usr/local)。

另外,您也可以从源代码下载/构建/安装它:

# download
curl -O -L http://effbot.org/media/downloads/Imaging-1.1.7.tar.gz
# extract
tar -xzf Imaging-1.1.7.tar.gz
cd Imaging-1.1.7
# build and install
python setup.py build
sudo python setup.py install
# or install it for just you without requiring admin permissions:
# python setup.py install --user

我刚刚(在OSX 10.7.2,XCode 4.2.1和System Python 2.7.1上)运行了上面的代码,尽管在我的环境中某些内容可能不是默认值,但它的构建还不错。

[homebrew]:http : //mxcl.github.com/homebrew/ “ Homebrew”

I take it you’re on Mac. See How can I install PIL on mac os x 10.7.2 Lion

If you use [homebrew][], you can install the PIL with just brew install pil. You may then need to add the install directory ($(brew --prefix)/lib/python2.7/site-packages) to your PYTHONPATH, or add the location of PIL directory itself in a file called PIL.pth file in any of your site-packages directories, with the contents:

/usr/local/lib/python2.7/site-packages/PIL

(assuming brew --prefix is /usr/local).

Alternatively, you can just download/build/install it from source:

# download
curl -O -L http://effbot.org/media/downloads/Imaging-1.1.7.tar.gz
# extract
tar -xzf Imaging-1.1.7.tar.gz
cd Imaging-1.1.7
# build and install
python setup.py build
sudo python setup.py install
# or install it for just you without requiring admin permissions:
# python setup.py install --user

I ran the above just now (on OSX 10.7.2, with XCode 4.2.1 and System Python 2.7.1) and it built just fine, though there is a possibility that something in my environment is non-default.

[homebrew]: http://mxcl.github.com/homebrew/ “Homebrew”


回答 8

如今,每个人都在PIL上使用友好的PIL叉子Pillow。

代替: sudo pip install pil

做: sudo pip install pillow

$ sudo apt-get install python-imaging
$ sudo -H pip install pillow

These days, everyone uses Pillow, a friendly PIL fork, over PIL.

Instead of: sudo pip install pil

Do: sudo pip install pillow

$ sudo apt-get install python-imaging
$ sudo -H pip install pillow

回答 9

对于Ubuntu,PIL不再起作用。我总是得到:

找不到与PIL匹配的分布

因此,安装python-imaging:

sudo apt-get install python-imaging

For Ubuntu, PIL is not working any more. I always get:

No matching distribution found for PIL

So install python-imaging:

sudo apt-get install python-imaging

回答 10

我遇到了同样的问题,但是通过安装 python-dev

在安装PIL之前,请运行以下命令:

sudo apt-get install python-dev

然后安装PIL:

pip install PIL

I’m having the same problem, but it gets solved with installation of python-dev.

Before installing PIL, run following command:

sudo apt-get install python-dev

Then install PIL:

pip install PIL

回答 11

安装过程中出现了一些错误。以防万一有人也有这个。尽管我已经是管理员用户,但不是root用户。

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/PIL'

Storing debug log for failure in /Users/wzbozon/Library/Logs/pip.log

添加“ sudo”解决了问题,使用sudo可以解决问题:

~/Documents/mv-server: $ sudo pip install Pillow

I had some errors during installation. Just in case somebody has this too. Despite that I already was sitting under admin user, but not root.

File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/PIL'

Storing debug log for failure in /Users/wzbozon/Library/Logs/pip.log

Adding “sudo” solved the problem, with sudo it worked:

~/Documents/mv-server: $ sudo pip install Pillow

回答 12

对于CentOS:

yum install python-imaging

For CentOS:

yum install python-imaging

回答 13

我尝试了所有答案,但失败了。直接从官方站点获取源代码,然后构建安装成功。

  1. 前往网站 http://www.pythonware.com/products/pil/#pil117
  2. 单击“ Python Imaging Library 1.1.7源工具包”以下载源
  3. tar xf Imaging-1.1.7.tar.gz
  4. cd Imaging-1.1.7
  5. sudo python setup.py install

I tried all the answers, but failed. Directly get the source from the official site and then build install success.

  1. Go to the site http://www.pythonware.com/products/pil/#pil117
  2. Click “Python Imaging Library 1.1.7 Source Kit” to download the source
  3. tar xf Imaging-1.1.7.tar.gz
  4. cd Imaging-1.1.7
  5. sudo python setup.py install

回答 14

我用 sudo port install py27-Pillow

I nailed it by using sudo port install py27-Pillow


回答 15

尝试这个:

sudo pip install PIL --allow-external PIL --allow-unverified PIL

Try this:

sudo pip install PIL --allow-external PIL --allow-unverified PIL

回答 16

(窗口)如果Pilow不起作用,请尝试从http://www.pythonware.com/products/pil/下载pil

(Window) If Pilow not work try download pil at http://www.pythonware.com/products/pil/


回答 17

  • 首先,您应该运行此程序sudo apt-get build-dep python-imaging,它将为您提供可能需要的所有依赖项

  • 然后跑 sudo apt-get update && sudo apt-get -y upgrade

  • 其次是 sudo apt-get install python-pip

  • 然后最后安装Pil pip install pillow

  • First you should run this sudo apt-get build-dep python-imaging which will give you all the dependencies that you might need

  • Then run sudo apt-get update && sudo apt-get -y upgrade

  • Followed by sudo apt-get install python-pip

  • And then finally install Pil pip install pillow


回答 18

使用之前,请先搜索软件包管理器pip。在Arch Linux上,您可以通过以下方式获取PIL:pacman -S python2-pillow

Search on package manager before using pip. On Arch linux you can get PIL by pacman -S python2-pillow


回答 19

还有另一个名为的Python打包工具conda。当某些库需要安装C ++和其他非纯Python的绑定时,Conda优于pip(我认为)。Conda的安装中还包括点子,因此您仍然可以使用点子,但您也可以从conda中受益。

默认情况下,Conda还安装IPython,pil和许多其他库。我想你会喜欢的。

There’s another Python package tool called conda. Conda is preferred (I believe) over pip when there are libraries that need to install C++ and other bindings that aren’t pure Python. Conda includes pip in its installation as well so you can still use pip, but you also get the benefits of conda.

Conda also installs IPython, pil, and many other libraries by default. I think you’ll like it.


如何安装适用于Python的yaml软件包?

问题:如何安装适用于Python的yaml软件包?

我有一个使用YAML的Python程序。我尝试使用将其安装在新服务器上pip install yaml,并且返回以下内容:

$ sudo pip install yaml
Downloading/unpacking yaml
  Could not find any downloads that satisfy the requirement yaml
No distributions at all found for yaml
Storing complete log in /home/pa/.pip/pip.log

如何安装适用于Python的yaml软件包?我正在运行Python 2.7。(作业系统:Debian Wheezy)

I have a Python program that uses YAML. I attempted to install it on a new server using pip install yaml and it returns the following:

$ sudo pip install yaml
Downloading/unpacking yaml
  Could not find any downloads that satisfy the requirement yaml
No distributions at all found for yaml
Storing complete log in /home/pa/.pip/pip.log

How do I install the yaml package for Python? I’m running Python 2.7. (OS: Debian Wheezy)


回答 0

您可以尝试点子搜索功能,

$ pip search yaml

它在简短说明中使用yaml在PyPI中查找软件包。这揭示了各种软件包,包括PyYaml,yamltools和PySyck等(请注意,PySyck文档建议使用PyYaml,因为syck已过时)。现在您知道了特定的软件包名称,可以安装它:

$ pip install pyyaml

如果要在linux系统范围内安装python yaml,也可以使用软件包管理器,例如aptitudeyum

$ sudo apt-get install python-yaml
$ sudo yum install python-yaml

You could try the search feature in pip,

$ pip search yaml

which looks for packages in PyPI with yaml in the short description. That reveals various packages, including PyYaml, yamltools, and PySyck, among others (Note that PySyck docs recommend using PyYaml, since syck is out of date). Now you know a specific package name, you can install it:

$ pip install pyyaml

If you want to install python yaml system-wide in linux, you can also use a package manager, like aptitude or yum:

$ sudo apt-get install python-yaml
$ sudo yum install python-yaml

回答 1

pip install pyyaml

如果没有pip,请运行easy_install pip安装pip,这是必备的软件包安装程序- 为什么在easy_install上使用pip?。如果您喜欢坚持使用easy_install,则easy_install pyyaml

pip install pyyaml

If you don’t have pip, run easy_install pip to install pip, which is the go-to package installer – Why use pip over easy_install?. If you prefer to stick with easy_install, then easy_install pyyaml


回答 2

更新:如今,安装已通过pip完成,但仍需要libyaml来构建C扩展(在Mac上):

brew install libyaml
python -m pip install pyyaml

过时的方法

对于MacOSX(小牛),以下方法似乎有效:

brew install libyaml
sudo python -m easy_install pyyaml

Update: Nowadays installing is done with pip, but libyaml is still required to build the C extension (on mac):

brew install libyaml
python -m pip install pyyaml

Outdated method:

For MacOSX (mavericks), the following seems to work:

brew install libyaml
sudo python -m easy_install pyyaml

回答 3

pip install PyYAML

如果找不到libyaml或编译的PyYAML可以在Mavericks上不使用它。

pip install PyYAML

If libyaml is not found or compiled PyYAML can do without it on Mavericks.


回答 4

有三个支持YAML的软件包。Syck(pip install syck),从2002年开始实施YAML 1.0规范;pip install pyyaml遵循2004年的YAML 1.1规范的PyYAML();和ruamel.yaml下面的最新(YAML 1.2,从2009年)规范。

您可以使用以下命令安装YAML 1.2兼容软件包,pip install ruamel.yaml或者如果您正在运行Debian / Ubuntu(或衍生版本)的现代版本,则可以使用:

sudo apt-get install python-ruamel.yaml

There are three YAML capable packages. Syck (pip install syck) which implements the YAML 1.0 specification from 2002; PyYAML (pip install pyyaml) which follows the YAML 1.1 specification from 2004; and ruamel.yaml which follows the latest (YAML 1.2, from 2009) specification.

You can install the YAML 1.2 compatible package with pip install ruamel.yaml or if you are running a modern version of Debian/Ubuntu (or derivative) with:

sudo apt-get install python-ruamel.yaml

回答 5

基于Debian的系统:

$ sudo aptitude install python-yaml

或更高版本的python3

$ sudo aptitude install python3-yaml

Debian-based systems:

$ sudo aptitude install python-yaml

or newer for python3

$ sudo aptitude install python3-yaml


回答 6

以下命令将下载pyyaml,其中还包括yaml

pip install pyYaml

following command will download pyyaml, which also includes yaml

pip install pyYaml

回答 7

“应该有一种-最好只有一种-显而易见的方法。” 因此,我再添加一个。这更像是Debian / Ubuntu的“从源代码安装”,来自https://github.com/yaml/pyyaml

安装libYAML及其标头:

sudo apt-get install libyaml-dev

下载 pyyaml来源:

wget http://pyyaml.org/download/pyyaml/PyYAML-3.13.tar.gz

从源代码安装(不要忘记激活您的venv):

. your/env/bin/activate
tar xzf PyYAML-3.13.tar.gz
cd PyYAML-3.13.tar.gz
(env)$ python setup.py install
(env)$ python setup.py test 

“There should be one — and preferably only one — obvious way to do it.” So let me add another one. This one is more like “install from sources” for Debian/Ubuntu, from https://github.com/yaml/pyyaml

Install the libYAML and it’s headers:

sudo apt-get install libyaml-dev

Download the pyyaml sources:

wget http://pyyaml.org/download/pyyaml/PyYAML-3.13.tar.gz

Install from sources, (don’t forget to activate your venv):

. your/env/bin/activate
tar xzf PyYAML-3.13.tar.gz
cd PyYAML-3.13.tar.gz
(env)$ python setup.py install
(env)$ python setup.py test 

回答 8

使用strictyaml代替

如果您可以自行创建yaml文件,或者不需要常规yaml的任何这些功能,则建议使用strictyaml而不是标准pyyaml软件包。

简而言之,默认yaml在安全性,接口和可预测性方面存在一些严重缺陷。strictyaml是yaml规范的一个子集,没有这些问题(并且有更好的记录)。

您可以在这里阅读更多有关常规Yaml问题的信息

意见: strictyaml应为yaml的默认实现,而旧的yaml规范应作废。

Use strictyaml instead

If you have the luxury of creating the yaml file yourself, or if you don’t require any of these features of regular yaml, I recommend using strictyaml instead of the standard pyyaml package.

In short, default yaml has some serious flaws in terms of security, interface, and predictability. strictyaml is a subset of the yaml spec that does not have those issues (and is better documented).

You can read more about the problems with regular yaml here

OPINION: strictyaml should be the default implementation of yaml and the old yaml spec should be obsoleted.


回答 9

对我来说,安装libyaml的开发版本即可。

yum install libyaml-devel         #centos
apt-get install libyaml-dev       # ubuntu

For me, installing development version of libyaml did it.

yum install libyaml-devel         #centos
apt-get install libyaml-dev       # ubuntu

将字典转换为JSON

问题:将字典转换为JSON

r = {'is_claimed': 'True', 'rating': 3.5}
r = json.dumps(r)
file.write(str(r['rating']))

我无法访问JSON中的数据。我究竟做错了什么?

TypeError: string indices must be integers, not str
r = {'is_claimed': 'True', 'rating': 3.5}
r = json.dumps(r)
file.write(str(r['rating']))

I am not able to access my data in the JSON. What am I doing wrong?

TypeError: string indices must be integers, not str

回答 0

json.dumps()将字典转换为str对象,而不是json(dict)对象!因此,您必须使用方法将其加载strdictjson.loads()

请参阅json.dumps()作为保存方法和json.loads()检索方法。

这是代码示例,可以帮助您进一步了解它:

import json

r = {'is_claimed': 'True', 'rating': 3.5}
r = json.dumps(r)
loaded_r = json.loads(r)
loaded_r['rating'] #Output 3.5
type(r) #Output str
type(loaded_r) #Output dict

json.dumps() converts a dictionary to str object, not a json(dict) object! So you have to load your str into a dict to use it by using json.loads() method

See json.dumps() as a save method and json.loads() as a retrieve method.

This is the code sample which might help you understand it more:

import json

r = {'is_claimed': 'True', 'rating': 3.5}
r = json.dumps(r)
loaded_r = json.loads(r)
loaded_r['rating'] #Output 3.5
type(r) #Output str
type(loaded_r) #Output dict

回答 1

json.dumps()返回python字典的JSON字符串表示形式。查看文件

您不能这样做,r['rating']因为r是字符串,不再是dict

也许你的意思是

r = {'is_claimed': 'True', 'rating': 3.5}
json = json.dumps(r) # note i gave it a different name
file.write(str(r['rating']))

json.dumps() returns the JSON string representation of the python dict. See the docs

You can’t do r['rating'] because r is a string, not a dict anymore

Perhaps you meant something like

r = {'is_claimed': 'True', 'rating': 3.5}
json = json.dumps(r) # note i gave it a different name
file.write(str(r['rating']))

回答 2

无需通过使用将其转换为字符串 json.dumps()

r = {'is_claimed': 'True', 'rating': 3.5}
file.write(r['is_claimed'])
file.write(str(r['rating']))

您可以直接从dict对象获取值。

No need to convert it in a string by using json.dumps()

r = {'is_claimed': 'True', 'rating': 3.5}
file.write(r['is_claimed'])
file.write(str(r['rating']))

You can get the values directly from the dict object.


回答 3

将r定义为字典应该可以解决这个问题:

>>> r: dict = {'is_claimed': 'True', 'rating': 3.5}
>>> print(r['rating'])
3.5
>>> type(r)
<class 'dict'>

Defining r as a dictionary should do the trick:

>>> r: dict = {'is_claimed': 'True', 'rating': 3.5}
>>> print(r['rating'])
3.5
>>> type(r)
<class 'dict'>

如何在Mac OS X 10.6.4上卸载Python 2.7?

问题:如何在Mac OS X 10.6.4上卸载Python 2.7?

我想从Mac OS X 10.6.4中完全删除Python 2.7。我设法PATH通过还原删除了变量中的条目.bash_profile。但我也想删除所有由python 2.7安装包安装的目录,文件,符号链接和条目。我从http://www.python.org/获得了安装包。我需要删除哪些目录/文件/配置文件条目?某处有清单吗?

I want to completely remove Python 2.7 from my Mac OS X 10.6.4. I managed to remove the entry from the PATH variable by reverting my .bash_profile. But I also want to remove all directories, files, symlinks, and entries that got installed by the Python 2.7 install package. I’ve got the install package from http://www.python.org/. What directories/files/configuration file entries do I need to remove? Is there a list somewhere?


回答 0

不要试图删除任何苹果公司提供的系统的Python这是在/System/Library/usr/bin,因为这可能会破坏你的整个操作系统。


注意: 以下列出的步骤不会影响Apple提供的系统Python 2.7;请参阅附录A。他们只会删除第三方Python框架,例如python.org安装程序安装的框架。


完整列表在此处记录。基本上,您需要做的是:

  1. 删除第三方Python 2.7框架

    sudo rm -rf /Library/Frameworks/Python.framework/Versions/2.7
  2. 删除Python 2.7应用程序目录

    sudo rm -rf "/Applications/Python 2.7"
  3. 在中删除/usr/local/bin指向此Python版本的符号链接。看到他们使用

    ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/2.7' 

    然后运行以下命令删除所有链接:

    cd /usr/local/bin/
    ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/2.7' | awk '{print $9}' | tr -d @ | xargs rm
  4. 如有必要,请编辑您的外壳配置文件,以删除添加/Library/Frameworks/Python.framework/Versions/2.7到您的PATH环境文件中的操作。根据您所使用的shell,任何下列文件可能已被修改: ~/.bash_login~/.bash_profile~/.cshrc~/.profile~/.tcshrc,和/或~/.zprofile

Do not attempt to remove any Apple-supplied system Python which are in /System/Library and /usr/bin, as this may break your whole operating system.


NOTE: The steps listed below do not affect the Apple-supplied system Python 2.7; they only remove a third-party Python framework, like those installed by python.org installers.


The complete list is documented here. Basically, all you need to do is the following:

  1. Remove the third-party Python 2.7 framework

    sudo rm -rf /Library/Frameworks/Python.framework/Versions/2.7
    
  2. Remove the Python 2.7 applications directory

    sudo rm -rf "/Applications/Python 2.7"
    
  3. Remove the symbolic links, in /usr/local/bin, that point to this Python version. See them using

    ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/2.7' 
    

    and then run the following command to remove all the links:

    cd /usr/local/bin/
    ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/2.7' | awk '{print $9}' | tr -d @ | xargs rm
    
  4. If necessary, edit your shell profile file(s) to remove adding /Library/Frameworks/Python.framework/Versions/2.7 to your PATH environment file. Depending on which shell you use, any of the following files may have been modified: ~/.bash_login, ~/.bash_profile, ~/.cshrc, ~/.profile, ~/.tcshrc, and/or ~/.zprofile.


回答 1

这个作品:

cd /usr/local/bin/
ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/2.7' | awk '{print $9}' | tr -d @ | xargs rm

描述:列出所有链接,删除@字符,然后删除它们。

This one works:

cd /usr/local/bin/
ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/2.7' | awk '{print $9}' | tr -d @ | xargs rm

Description: It list all the links, removes @ character and then removes them.


回答 2

如果使用PKG安装程序安装了它,则可以执行以下操作:

pkgutil --pkgs

或更好:

pkgutil --pkgs | grep org.python.Python

这将输出类似:

org.python.Python.PythonApplications-2.7
org.python.Python.PythonDocumentation-2.7
org.python.Python.PythonFramework-2.7
org.python.Python.PythonProfileChanges-2.7
org.python.Python.PythonUnixTools-2.7

您现在可以选择要取消链接(删除)的软件包。

这是取消链接文档:

 --unlink package-id
             Unlinks (removes) each file referenced by package-id. WARNING: This command makes no attempt to perform reference counting or dependency analy-
             sis. It can easily remove files required by your system. It may include unexpected files due to package tainting. Use the --files command first
             to double check.

在我的示例中,您将输入

pkgutil --unlink org.python.Python.PythonApplications-2.7
pkgutil --unlink org.python.Python.PythonDocumentation-2.7
pkgutil --unlink org.python.Python.PythonFramework-2.7
pkgutil --unlink org.python.Python.PythonProfileChanges-2.7
pkgutil --unlink org.python.Python.PythonUnixTools-2.7

或一行:

pkgutil --pkgs | grep org.python.Python | xargs -L1 pkgutil -f --unlink

重要提示:–unlink从Lion(从2014年第一季度开始,包括Lion,Mountain Lion和Mavericks)不再可用。如果涉及此说明的任何人都尝试将其与狮子一起使用,则应尝试改编本文所讲的内容:https : //wincent.com/wiki/Uninstalling_packages_(.pkg_files)_on_Mac_OS_X

If you installed it using the PKG installer, you can do:

pkgutil --pkgs

or better:

pkgutil --pkgs | grep org.python.Python

which will output something like:

org.python.Python.PythonApplications-2.7
org.python.Python.PythonDocumentation-2.7
org.python.Python.PythonFramework-2.7
org.python.Python.PythonProfileChanges-2.7
org.python.Python.PythonUnixTools-2.7

you can now select which packages you will unlink (remove).

This is the unlink documentation:

 --unlink package-id
             Unlinks (removes) each file referenced by package-id. WARNING: This command makes no attempt to perform reference counting or dependency analy-
             sis. It can easily remove files required by your system. It may include unexpected files due to package tainting. Use the --files command first
             to double check.

In my example you will type

pkgutil --unlink org.python.Python.PythonApplications-2.7
pkgutil --unlink org.python.Python.PythonDocumentation-2.7
pkgutil --unlink org.python.Python.PythonFramework-2.7
pkgutil --unlink org.python.Python.PythonProfileChanges-2.7
pkgutil --unlink org.python.Python.PythonUnixTools-2.7

or in one single line:

pkgutil --pkgs | grep org.python.Python | xargs -L1 pkgutil -f --unlink

Important: –unlink is not available anymore starting with Lion (as of Q1`2014 that would include Lion, Mountain Lion, and Mavericks). If anyone that comes to this instructions try to use it with lion, should try instead to adapt it with what this post is saying: https://wincent.com/wiki/Uninstalling_packages_(.pkg_files)_on_Mac_OS_X


回答 3

尝试使用卸载Python

brew uninstall python

不会删除本机安装了Python,而是版本安装brew

Trying to uninstall Python with

brew uninstall python

will not remove the natively installed Python but rather the version installed with brew.


回答 4

关于删除符号链接,我发现这很有用。

find /usr/local/bin -lname '../../../Library/Frameworks/Python.framework/Versions/2.7/*' -delete

In regards to deleting the symbolic links, I found this to be useful.

find /usr/local/bin -lname '../../../Library/Frameworks/Python.framework/Versions/2.7/*' -delete

回答 5

创建符号链接到最新版本

 ln -s -f /usr/local/bin/python3.8 /usr/local/bin/python

关闭并打开一个新终端

并尝试

 python --version

Create the symlink to latest version

 ln -s -f /usr/local/bin/python3.8 /usr/local/bin/python

Close and open a new terminal

and try

 python --version

回答 6

无需卸载旧的python版本。

只需安装新版本,说python-3.3.2-macosx10.6.dmg并将python的软链接更改为新安装的python3.3

使用以下命令检查默认python和python3.3的路径

“哪个python”和“哪个python3.3”

然后删除python的现有软链接并将其指向python3.3

No need to uninstall old python versions.

Just install new version say python-3.3.2-macosx10.6.dmg and change the soft link of python to newly installed python3.3

Check the path of default python and python3.3 with following commands

“which python” and “which python3.3”

then delete existing soft link of python and point it to python3.3


回答 7

OnurGüzel在他的博客文章“从OS X卸载Python包”中提供了解决方案。

您应该在终端中键入以下命令:

  1. sudo rm -rf /Library/Frameworks/Python.framework
  2. cd /usr/local/bin
  3. ls -l . | grep '../Library/Frameworks/Python.framework' | awk '{print $9}' | xargs sudo rm
  4. sudo rm -rf "/Applications/Python x.y"

    其中命令xy是安装的Python版本。根据您的问题,应该是2.7。

用Onur的话来说:

警告:此命令将删除与软件包一起安装的所有Python版本。系统提供的Python不会受到影响。

如果您从python.org安装了多个Python版本,请再次运行第四个命令,为每个要卸载的Python版本更改“ xy”。

Onur Güzel provides the solution in his blog post, “Uninstall Python Package from OS X.

You should type the following commands into the terminal:

  1. sudo rm -rf /Library/Frameworks/Python.framework
  2. cd /usr/local/bin
  3. ls -l . | grep '../Library/Frameworks/Python.framework' | awk '{print $9}' | xargs sudo rm
  4. sudo rm -rf "/Applications/Python x.y"

    where command x.y is the version of Python installed. According to your question, it should be 2.7.

In Onur’s words:

WARNING: This commands will remove all Python versions installed with packages. Python provided from the system will not be affected.

If you have more than 1 Python version installed from python.org, then run the fourth command again, changing “x.y” for each version of Python that is to be uninstalled.


回答 8

注意如果使用Homebrew安装了Python,则可以按照以下步骤操作,否则请寻找其他解决方案!


要卸载使用Homebrew安装的Python 2.7.10,可以简单地发出以下命令:

brew uninstall python

同样,如果要卸载Python 3(使用Homebrew安装),请执行以下操作:

brew uninstall --force python3

Note: If you installed Python using Homebrew, then you can follow the following steps, otherwise look for another solution!


To uninstall Python 2.7.10 which you installed using Homebrew, then you can simply issue the following command:

brew uninstall python

Similarly, if you want to uninstall Python 3 (which you installed using Homebrew):

brew uninstall --force python3

回答 9

无需卸载它或使用符号链接发疯,只需使用即可alias。升级到python 3.7.1时,我遇到了同样的问题。
只需使用安装新的python版本,brew install python然后在.bash_profile创建的别名中指向新的python版本即可;这样:alias python="/usr/local/bin/python3"然后保存并运行source ~/.bash_profile
做完了

No need to uninstall it or going crazy with symbolic links, just use an alias. I faced the same problem when upgrading to python 3.7.1.
Just install the new python version using brew install python then in your .bash_profile create an alias pointing to the new python version; like this: alias python="/usr/local/bin/python3" then save and run source ~/.bash_profile.
Done.


回答 10

如果您正在考虑手动删除Apple的默认Python 2.7,建议您立即执行以下操作:看起来Apple很快会为您完成此操作:

OSX 10.15 Catalina中不推荐使用Python 2.7

Catalina中不推荐使用Python 2.7-以及Ruby和Perl :(跳至“ 脚本语言运行时 ”>“ 不推荐使用 ”部分)

https://developer.apple.com/documentation/macos_release_notes/macos_catalina_10_15_release_notes

苹果将​​在OSX 10.16中删除Python 2.7

确实,如果您什么都不做,那么根据OS X版本10.16 的Mac Observer所述,Python 2.7将从您的系统中消失:

https://www.macobserver.com/analysis/macos-catalina-deprecates-unix-scripting-languages/

鉴于这一启示,我建议最好的做法是什么也不做,等待苹果为您清除。由于Apple即将为您删除它,因此似乎不值得尝试修改您的Python环境。

注意:我看到这个问题专门与OSX v 10.6.4有关,但是对于所有有兴趣从其系统中删除Python 2.7的OSX人士,无论他们运行的是哪个版本,该问题似乎都已成为一个关键点。

If you’re thinking about manually removing Apple’s default Python 2.7, I’d suggest you hang-fire and do-noting: Looks like Apple will very shortly do it for you:

Python 2.7 Deprecated in OSX 10.15 Catalina

Python 2.7- as well as Ruby & Perl- are deprecated in Catalina: (skip to section “Scripting Language Runtimes” > “Deprecations“)

https://developer.apple.com/documentation/macos_release_notes/macos_catalina_10_15_release_notes

Apple To Remove Python 2.7 in OSX 10.16

Indeed, if you do nothing at all, according to The Mac Observer, by OSX version 10.16, Python 2.7 will disappear from your system:

https://www.macobserver.com/analysis/macos-catalina-deprecates-unix-scripting-languages/

Given this revelation, I’d suggest the best course of action is do nothing and wait for Apple to wipe it for you. As Apple is imminently about to remove it for you, doesn’t seem worth the risk of tinkering with your Python environment.

NOTE: I see the question relates specifically to OSX v 10.6.4, but it appears this question has become a pivot-point for all OSX folks interested in removing Python 2.7 from their systems, whatever version they’re running.


在Python中将列表转换为元组

问题:在Python中将列表转换为元组

我正在尝试将列表转换为元组。

Google上的大多数解决方案都提供以下代码:

l = [4,5,6]
tuple(l)

但是,运行该代码会导致错误消息:

TypeError:“元组”对象不可调用如何解决此问题?

I’m trying to convert a list to a tuple.

Most solutions on Google offer the following code:

l = [4,5,6]
tuple(l)

However, the code results in an error message when I run it:

TypeError: ‘tuple’ object is not callable How can I fix this problem?


回答 0

它应该工作正常。不要使用tuplelist或其他特殊的名字作为变量名。这可能是导致您出现问题的原因。

>>> l = [4,5,6]
>>> tuple(l)
(4, 5, 6)

It should work fine. Don’t use tuple, list or other special names as a variable name. It’s probably what’s causing your problem.

>>> l = [4,5,6]
>>> tuple(l)
(4, 5, 6)

回答 1

扩展eumiro的注释,通常tuple(l)会将列表l转换为元组:

In [1]: l = [4,5,6]

In [2]: tuple
Out[2]: <type 'tuple'>

In [3]: tuple(l)
Out[3]: (4, 5, 6)

但是,如果您已重新定义tuple为元组而不是type tuple

In [4]: tuple = tuple(l)

In [5]: tuple
Out[5]: (4, 5, 6)

那么您会收到TypeError,因为元组本身不可调用:

In [6]: tuple(l)
TypeError: 'tuple' object is not callable

您可以tuple通过退出并重新启动解释器来恢复原始定义,或者(感谢@glglgl):

In [6]: del tuple

In [7]: tuple
Out[7]: <type 'tuple'>

Expanding on eumiro’s comment, normally tuple(l) will convert a list l into a tuple:

In [1]: l = [4,5,6]

In [2]: tuple
Out[2]: <type 'tuple'>

In [3]: tuple(l)
Out[3]: (4, 5, 6)

However, if you’ve redefined tuple to be a tuple rather than the type tuple:

In [4]: tuple = tuple(l)

In [5]: tuple
Out[5]: (4, 5, 6)

then you get a TypeError since the tuple itself is not callable:

In [6]: tuple(l)
TypeError: 'tuple' object is not callable

You can recover the original definition for tuple by quitting and restarting your interpreter, or (thanks to @glglgl):

In [6]: del tuple

In [7]: tuple
Out[7]: <type 'tuple'>

回答 2

您可能已经做过这样的事情:

>>> tuple = 45, 34  # You used `tuple` as a variable here
>>> tuple
(45, 34)
>>> l = [4, 5, 6]
>>> tuple(l)   # Will try to invoke the variable `tuple` rather than tuple type.

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    tuple(l)
TypeError: 'tuple' object is not callable
>>>
>>> del tuple  # You can delete the object tuple created earlier to make it work
>>> tuple(l)
(4, 5, 6)

这是问题所在…由于您使用了tuple变量来保存tuple (45, 34)较早的内容…所以,现在tupleobject类型tuple

它不再是一个type,因此不再Callable

Never使用任何内置类型作为变量名…您确实可以使用任何其他名称。请为变量使用任意名称…

You might have done something like this:

>>> tuple = 45, 34  # You used `tuple` as a variable here
>>> tuple
(45, 34)
>>> l = [4, 5, 6]
>>> tuple(l)   # Will try to invoke the variable `tuple` rather than tuple type.

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    tuple(l)
TypeError: 'tuple' object is not callable
>>>
>>> del tuple  # You can delete the object tuple created earlier to make it work
>>> tuple(l)
(4, 5, 6)

Here’s the problem… Since you have used a tuple variable to hold a tuple (45, 34) earlier… So, now tuple is an object of type tuple now…

It is no more a type and hence, it is no more Callable.

Never use any built-in types as your variable name… You do have any other name to use. Use any arbitrary name for your variable instead…


回答 3

tuple(l)自Python> =起,要向中添加其他替代方法,3.5您可以执行以下操作:

t = *l,  # or t = (*l,) 

简短一点快,但可能是从可读性受到影响。

这实际上将列表解压缩到l元组文字中,该元组文字是由于单个逗号的存在而创建的,


Ps:您收到的错误是由于名称的掩盖所致,tuple即您在某处(例如)分配了名称元组tuple = (1, 2, 3)

使用del tuple您应该很好。

To add another alternative to tuple(l), as of Python >= 3.5 you can do:

t = *l,  # or t = (*l,) 

short, a bit faster but probably suffers from readability.

This essentially unpacks the list l inside a tuple literal which is created due to the presence of the single comma ,.


P.s: The error you are receiving is due to masking of the name tuple i.e you assigned to the name tuple somewhere e.g tuple = (1, 2, 3).

Using del tuple you should be good to go.


回答 4

我找到了许多最新的答案,并且得到了正确答案,但会为答案添加一些新内容。

在Python有无限的方法可以做到这一点,这里有一些情况下,
正常的方式

>>> l= [1,2,"stackoverflow","python"]
>>> l
[1, 2, 'stackoverflow', 'python']
>>> tup = tuple(l)
>>> type(tup)
<type 'tuple'>
>>> tup
(1, 2, 'stackoverflow', 'python')

聪明的方法

>>>tuple(item for item in l)
(1, 2, 'stackoverflow', 'python')

请记住,元组是不变的,用于存储有价值的东西。例如,密码,密钥或哈希存储在元组或字典中。如果需要刀,为什么要用剑切苹果。明智地使用它,还可以使您的程序高效。

I find many answers up to date and properly answered but will add something new to stack of answers.

In python there are infinite ways to do this, here are some instances
Normal way

>>> l= [1,2,"stackoverflow","python"]
>>> l
[1, 2, 'stackoverflow', 'python']
>>> tup = tuple(l)
>>> type(tup)
<type 'tuple'>
>>> tup
(1, 2, 'stackoverflow', 'python')

smart way

>>>tuple(item for item in l)
(1, 2, 'stackoverflow', 'python')

Remember tuple is immutable ,used for storing something valuable. For example password,key or hashes are stored in tuples or dictionaries. If knife is needed why to use sword to cut apples. Use it wisely, it will also make your program efficient.


为什么“ [False,True]中的not(True)”返回False?

问题:为什么“ [False,True]中的not(True)”返回False?

如果我这样做:

>>> False in [False, True]
True

那又回来了True。仅仅是因为False在列表中。

但是如果我这样做:

>>> not(True) in [False, True]
False

那又回来了False。而not(True)等于False

>>> not(True)
False

为什么?

If I do this:

>>> False in [False, True]
True

That returns True. Simply because False is in the list.

But if I do:

>>> not(True) in [False, True]
False

That returns False. Whereas not(True) is equal to False:

>>> not(True)
False

Why?


回答 0

运算符优先级 2.x3.x。的优先级not低于的优先级in。因此,它等效于:

>>> not ((True) in [False, True])
False

这就是你想要的:

>>> (not True) in [False, True]
True

正如@Ben指出的:建议从不写not(True),而不是not True。前者使它看起来像一个函数调用,而它却not是一个运算符,而不是一个函数。

Operator precedence 2.x, 3.x. The precedence of not is lower than that of in. So it is equivalent to:

>>> not ((True) in [False, True])
False

This is what you want:

>>> (not True) in [False, True]
True

As @Ben points out: It’s recommended to never write not(True), prefer not True. The former makes it look like a function call, while not is an operator, not a function.


回答 1

not x in y 被评估为 x not in y

您可以通过反汇编代码来确切了解正在发生的事情。第一种情况按您的预期工作:

>>> x = lambda: False in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (False)
              3 LOAD_GLOBAL              0 (False)
              6 LOAD_GLOBAL              1 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               6 (in)
             15 RETURN_VALUE

第二种情况计算为True not in [False, True]False显然是:

>>> x = lambda: not(True) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              1 (False)
              6 LOAD_GLOBAL              0 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               7 (not in)
             15 RETURN_VALUE        
>>> 

您想要表达的是(not(True)) in [False, True],正如True您所期望的那样,您可以看到原因:

>>> x = lambda: (not(True)) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 UNARY_NOT           
              4 LOAD_GLOBAL              1 (False)
              7 LOAD_GLOBAL              0 (True)
             10 BUILD_LIST               2
             13 COMPARE_OP               6 (in)
             16 RETURN_VALUE        

not x in y is evaluated as x not in y

You can see exactly what’s happening by disassembling the code. The first case works as you expect:

>>> x = lambda: False in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (False)
              3 LOAD_GLOBAL              0 (False)
              6 LOAD_GLOBAL              1 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               6 (in)
             15 RETURN_VALUE

The second case, evaluates to True not in [False, True], which is False clearly:

>>> x = lambda: not(True) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              1 (False)
              6 LOAD_GLOBAL              0 (True)
              9 BUILD_LIST               2
             12 COMPARE_OP               7 (not in)
             15 RETURN_VALUE        
>>> 

What you wanted to express instead was (not(True)) in [False, True], which as expected is True, and you can see why:

>>> x = lambda: (not(True)) in [False, True]
>>> dis.dis(x)
  1           0 LOAD_GLOBAL              0 (True)
              3 UNARY_NOT           
              4 LOAD_GLOBAL              1 (False)
              7 LOAD_GLOBAL              0 (True)
             10 BUILD_LIST               2
             13 COMPARE_OP               6 (in)
             16 RETURN_VALUE        

回答 2

运算符优先级。in绑定比紧密not,因此您的表达式等效于not((True) in [False, True])

Operator precedence. in binds more tightly than not, so your expression is equivalent to not((True) in [False, True]).


回答 3

一切都与运算符优先级有关in比强大not)。但是可以通过在适当的位置添加括号来轻松地纠正它:

(not(True)) in [False, True]  # prints true

写作:

not(True) in [False, True]

就像这样:

not((True) in [False, True])

它看起来是否True在列表中,并返回结果的“ not”。

It’s all about operator precedence (in is stronger than not). But it can be easily corrected by adding parentheses at the right place:

(not(True)) in [False, True]  # prints true

writing:

not(True) in [False, True]

is the same like:

not((True) in [False, True])

which looks if True is in the list and returns the “not” of the result.


回答 4

它的计算结果为not True in [False, True]False由于True位于中而返回[False, True]

如果你试试

>>>(not(True)) in [False, True]
True

您会得到预期的结果。

It is evaluating as not True in [False, True], which returns False because True is in [False, True]

If you try

>>>(not(True)) in [False, True]
True

You get the expected result.


回答 5

除了提到优先级not低于的其他答案in,实际上您的陈述还等同于:

not (True in [False, True])

但请注意,如果您不将条件与其他条件分开,则python将使用2个角色(precedencechaining)将其分开,在这种情况下,python使用优先级。另外,请注意,如果要分隔条件,则需要将所有条件放在括号中,而不仅是对象或值:

(not True) in [False, True]

但是如前所述,python对运算符进行了另一种修改,即链接

基于python 文档

请注意,比较,成员资格测试和身份测试均具有相同的优先级,并且具有“比较”部分中所述的从左到右的链接功能。

例如,以下语句的结果是False

>>> True == False in [False, True]
False

因为python将像下面这样链接语句:

(True == False) and (False in [False, True])

确切的False and TrueFalse

您可以假定中心对象将在2个操作和其他对象之间共享(在这种情况下为False)。

并注意,对于所有比较,包括隶属度测试和身份测试操作(其后为操作数),它也适用:

in, not in, is, is not, <, <=, >, >=, !=, ==

范例:

>>> 1 in [1,2] == True
False

另一个著名的例子是数字范围:

7<x<20

等于:

7<x and x<20   

Alongside the other answers that mentioned the precedence of not is lower than in, actually your statement is equivalent to :

not (True in [False, True])

But note that if you don’t separate your condition from the other ones, python will use 2 roles (precedence or chaining) in order to separate that, and in this case python used precedence. Also, note that if you want to separate a condition you need to put all the condition in parenthesis not just the object or value :

(not True) in [False, True]

But as mentioned, there is another modification by python on operators that is chaining:

Based on python documentation :

Note that comparisons, membership tests, and identity tests, all have the same precedence and have a left-to-right chaining feature as described in the Comparisons section.

For example the result of following statement is False:

>>> True == False in [False, True]
False

Because python will chain the statements like following :

(True == False) and (False in [False, True])

Which exactly is False and True that is False.

You can assume that the central object will be shared between 2 operations and other objects (False in this case).

And note that its also true for all Comparisons, including membership tests and identity tests operations which are following operands :

in, not in, is, is not, <, <=, >, >=, !=, ==

Example :

>>> 1 in [1,2] == True
False

Another famous example is number range :

7<x<20

which is equal to :

7<x and x<20   

回答 6

让我们将其视为集合包含检查操作:[False, True]是包含一些元素的列表。

表达式True in [False, True]返回True,就像True列表中包含的元素一样。

因此,not True in [False, True]给出not上述表达式的“布尔相反” (没有任何括号可保留优先级,因为in优先级大于not运算符)。因此,not True将导致False

在另一方面,(not True) in [False, True]是等于False in [False, True],这是TrueFalse被包含在列表中)。

Let’s see it as a collection containment checking operation: [False, True] is a list containing some elements.

The expression True in [False, True] returns True, as True is an element contained in the list.

Therefore, not True in [False, True] gives the “boolean opposite”, not result of the above expression (without any parentheses to preserve precedence, as in has greater precedence than not operator). Therefore, not True will result False.

On the other hand, (not True) in [False, True], is equal to False in [False, True], which is True (False is contained in the list).


回答 7

为了阐明其他一些答案,一元运算符添加括号不会更改其优先级。not(True)不会使not绑定更紧密True。这只是一个多余的括号True。与大致相同(True) in [True, False]。括号不做任何事情。如果要使绑定更紧密,则必须在整个表达式两边加上括号,这意味着运算符和操作数(即)(not True) in [True, False]

要以另一种方式查看,请考虑

>>> -2**2
-4

**绑定比紧密-,这就是为什么要得到两个平方的负数,而不是两个负数的平方(也就是正四个)的原因。

如果您确实想要负二的平方怎么办?显然,您需要添加括号:

>>> (-2)**2
4

但是,期望以下内容不合理 4

>>> -(2)**2
-4

因为-(2)和一样-2。括号绝对不起作用。not(True)完全一样

To clarify on some of the other answers, adding parentheses after a unary operator does not change its precedence. not(True) does not make not bind more tightly to True. It’s just a redundant set of parentheses around True. It’s much the same as (True) in [True, False]. The parentheses don’t do anything. If you want the binding to be more tight, you have to put the parentheses around the whole expression, meaning both the operator and the operand, i.e., (not True) in [True, False].

To see this another way, consider

>>> -2**2
-4

** binds more tightly than -, which is why you get the negative of two squared, not the square of negative two (which would be positive four).

What if you did want the square of negative two? Obviously, you’d add parentheses:

>>> (-2)**2
4

However, it’s not reasonable to expect the following to give 4

>>> -(2)**2
-4

because -(2) is the same as -2. The parentheses do absolutely nothing. not(True) is exactly the same.


如何解决:“ UnicodeDecodeError:’ascii’编解码器无法解码字节”

问题:如何解决:“ UnicodeDecodeError:’ascii’编解码器无法解码字节”

as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!

如何解决?

在其他基于python的静态博客应用中,中文帖子可以成功发布。像这个程序:http : //github.com/vrypan/bucket3。在我的网站http://bc3.brite.biz/中,中文帖子可以成功发布。

as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!

How to fix it?

In some other python-based static blog apps, Chinese post can be published successfully. Such as this app: http://github.com/vrypan/bucket3. In my site http://bc3.brite.biz/, Chinese post can be published successfully.


回答 0

tl; dr /快速修复

  • 不要对Willy Nilly进行解码/编码
  • 不要假设您的字符串是UTF-8编码的
  • 尝试在代码中尽快将字符串转换为Unicode字符串
  • 修复您的语言环境:如何在Python 3.6中解决UnicodeDecodeError?
  • 不要试图使用快速reloadhack

Python 2.x中的Unicode Zen-完整版

在没有看到来源的情况下,很难知道根本原因,因此,我将不得不大体讲。

UnicodeDecodeError: 'ascii' codec can't decode byte通常,当您尝试将str包含非ASCII 的Python 2.x转换为Unicode字符串而未指定原始字符串的编码时,通常会发生这种情况。

简而言之,Unicode字符串是一种完全独立的Python字符串类型,不包含任何编码。它们仅保存Unicode 点代码,因此可以保存整个频谱中的任何Unicode点。字符串包含编码的文本,包括UTF-8,UTF-16,ISO-8895-1,GBK,Big5等。字符串被解码为Unicode,Unicodes被编码为字符串。文件和文本数据始终以编码的字符串传输。

Markdown模块的作者可能会使用unicode()(抛出异常的地方)作为其余代码的质量门-它会转换ASCII或将现有的Unicode字符串重新包装为新的Unicode字符串。Markdown作者不知道传入字符串的编码,因此在传递给Markdown之前,将依靠您将字符串解码为Unicode字符串。

可以使用u字符串前缀在代码中声明Unicode 字符串。例如

>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>

Unicode字符串也可能来自文件,数据库和网络模块。发生这种情况时,您无需担心编码。

陷阱

str即使不显式调用,也可能会发生从Unicode到Unicode的转换unicode()

以下情况导致UnicodeDecodeError异常:

# Explicit conversion without encoding
unicode('€')

# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')

# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'

# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'         

例子

在下图中,您可以看到如何café根据终端类型以“ UTF-8”或“ Cp1252”编码方式对单词进行编码。在两个示例中,caf都是常规的ascii。在UTF-8中,é使用两个字节进行编码。在“ Cp1252”中,é是0xE9(它也恰好是Unicode点值(这不是巧合))。正确的decode()被调用,并成功转换为Python Unicode: 将字符串转换为Python Unicode字符串的图

在此图中,使用decode()调用ascii(与unicode()没有给出编码的调用相同)。由于ASCII不能包含大于的字节0x7F,这将引发UnicodeDecodeError异常:

将字符串转换为编码错误的Python Unicode字符串的图

Unicode三明治

最好在代码中形成一个Unicode三明治,将所有传入数据解码为Unicode字符串,使用Unicode,然后在输出时编码为strs。这使您不必担心代码中间的字符串编码。

输入/解码

源代码

如果您需要将非ASCII烘烤到源代码中,只需通过在字符串前面加上来创建Unicode字符串u。例如

u'Zürich'

为了允许Python解码您的源代码,您将需要添加一个编码标头以匹配文件的实际编码。例如,如果您的文件编码为“ UTF-8”,则可以使用:

# encoding: utf-8

仅当源代码中包含非ASCII时才需要这样做。

档案

通常从文件接收非ASCII数据。该io模块提供了一个TextWrapper,它使用给定即时解码您的文件encoding。您必须为文件使用正确的编码-不容易猜测。例如,对于UTF-8文件:

import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
     my_unicode_string = my_file.read() 

my_unicode_string然后适合传递给Markdown。如果UnicodeDecodeErrorread()行开始,则您可能使用了错误的编码值。

CSV文件

Python 2.7 CSV模块不支持非ASCII字符😩。但是,https://pypi.python.org/pypi/backports.csv提供了帮助

像上面一样使用它,但是将打开的文件传递给它:

from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
    for row in csv.reader(my_file):
        yield row

资料库

大多数Python数据库驱动程序都可以Unicode格式返回数据,但是通常需要一些配置。始终对SQL查询使用Unicode字符串。

的MySQL

在连接字符串中添加:

charset='utf8',
use_unicode=True

例如

>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL的

加:

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)

HTTP

网页几乎可以采用任何编码方式进行编码。的Content-type报头应包含一个charset字段在编码暗示。然后可以根据该值手动解码内容。另外,Python-Requests在中返回Unicode response.text

手动地

如果必须手动解码字符串,则可以简单地执行my_string.decode(encoding),其中encoding是适当的编码。此处提供了Python 2.x支持的编解码器:标准编码。同样,如果您得到了,UnicodeDecodeError则可能是编码错误。

三明治的肉

像正常strs一样使用Unicode。

输出量

标准输出/打印

print通过标准输出流进行写入。Python尝试在stdout上配置编码器,以便将Unicode编码为控制台的编码。例如,如果Linux shell localeen_GB.UTF-8,则输出将被编码为UTF-8。在Windows上,您将被限制为8位代码页。

错误配置的控制台(例如损坏的语言环境)可能导致意外的打印错误。PYTHONIOENCODING环境变量可以强制对stdout进行编码。

档案

就像输入一样,io.open可用于将Unicode透明地转换为编码的字节字符串。

数据库

用于读取的相同配置将允许直接编写Unicode。

Python 3

Python 3不再比Python 2.x更具有Unicode功能,但是在该主题上的混淆却稍少一些。例如,常规str字符串现在是Unicode字符串,而旧字符串str现在是bytes

默认编码为UTF-8,因此,如果您.decode()未提供编码的字节字符串,Python 3将使用UTF-8编码。这可能解决了50%的人们的Unicode问题。

此外,open()默认情况下以文本模式运行,因此返回解码str(Unicode 编码)。编码来自您的语言环境,在Un * x系统上通常是UTF-8,在Windows机器上通常是8位代码页,例如Windows-1251。

为什么不应该使用 sys.setdefaultencoding('utf8')

这是一个令人讨厌的hack(这是您不得不使用的原因reload),只会掩盖问题并阻碍您迁移到Python3.x。理解问题,解决根本原因并享受Unicode zen。请参阅为什么我们不应该在py脚本中使用sys.setdefaultencoding(“ utf-8”)?了解更多详情

tl;dr / quick fix

  • Don’t decode/encode willy nilly
  • Don’t assume your strings are UTF-8 encoded
  • Try to convert strings to Unicode strings as soon as possible in your code
  • Fix your locale: How to solve UnicodeDecodeError in Python 3.6?
  • Don’t be tempted to use quick reload hacks

Unicode Zen in Python 2.x – The Long Version

Without seeing the source it’s difficult to know the root cause, so I’ll have to speak generally.

UnicodeDecodeError: 'ascii' codec can't decode byte generally happens when you try to convert a Python 2.x str that contains non-ASCII to a Unicode string without specifying the encoding of the original string.

In brief, Unicode strings are an entirely separate type of Python string that does not contain any encoding. They only hold Unicode point codes and therefore can hold any Unicode point from across the entire spectrum. Strings contain encoded text, beit UTF-8, UTF-16, ISO-8895-1, GBK, Big5 etc. Strings are decoded to Unicode and Unicodes are encoded to strings. Files and text data are always transferred in encoded strings.

The Markdown module authors probably use unicode() (where the exception is thrown) as a quality gate to the rest of the code – it will convert ASCII or re-wrap existing Unicodes strings to a new Unicode string. The Markdown authors can’t know the encoding of the incoming string so will rely on you to decode strings to Unicode strings before passing to Markdown.

Unicode strings can be declared in your code using the u prefix to strings. E.g.

>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>

Unicode strings may also come from file, databases and network modules. When this happens, you don’t need to worry about the encoding.

Gotchas

Conversion from str to Unicode can happen even when you don’t explicitly call unicode().

The following scenarios cause UnicodeDecodeError exceptions:

# Explicit conversion without encoding
unicode('€')

# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')

# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'

# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'         

Examples

In the following diagram, you can see how the word café has been encoded in either “UTF-8” or “Cp1252” encoding depending on the terminal type. In both examples, caf is just regular ascii. In UTF-8, é is encoded using two bytes. In “Cp1252”, é is 0xE9 (which is also happens to be the Unicode point value (it’s no coincidence)). The correct decode() is invoked and conversion to a Python Unicode is successfull: Diagram of a string being converted to a Python Unicode string

In this diagram, decode() is called with ascii (which is the same as calling unicode() without an encoding given). As ASCII can’t contain bytes greater than 0x7F, this will throw a UnicodeDecodeError exception:

Diagram of a string being converted to a Python Unicode string with the wrong encoding

The Unicode Sandwich

It’s good practice to form a Unicode sandwich in your code, where you decode all incoming data to Unicode strings, work with Unicodes, then encode to strs on the way out. This saves you from worrying about the encoding of strings in the middle of your code.

Input / Decode

Source code

If you need to bake non-ASCII into your source code, just create Unicode strings by prefixing the string with a u. E.g.

u'Zürich'

To allow Python to decode your source code, you will need to add an encoding header to match the actual encoding of your file. For example, if your file was encoded as ‘UTF-8’, you would use:

# encoding: utf-8

This is only necessary when you have non-ASCII in your source code.

Files

Usually non-ASCII data is received from a file. The io module provides a TextWrapper that decodes your file on the fly, using a given encoding. You must use the correct encoding for the file – it can’t be easily guessed. For example, for a UTF-8 file:

import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
     my_unicode_string = my_file.read() 

my_unicode_string would then be suitable for passing to Markdown. If a UnicodeDecodeError from the read() line, then you’ve probably used the wrong encoding value.

CSV Files

The Python 2.7 CSV module does not support non-ASCII characters 😩. Help is at hand, however, with https://pypi.python.org/pypi/backports.csv.

Use it like above but pass the opened file to it:

from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
    for row in csv.reader(my_file):
        yield row

Databases

Most Python database drivers can return data in Unicode, but usually require a little configuration. Always use Unicode strings for SQL queries.

MySQL

In the connection string add:

charset='utf8',
use_unicode=True

E.g.

>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
PostgreSQL

Add:

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)

HTTP

Web pages can be encoded in just about any encoding. The Content-type header should contain a charset field to hint at the encoding. The content can then be decoded manually against this value. Alternatively, Python-Requests returns Unicodes in response.text.

Manually

If you must decode strings manually, you can simply do my_string.decode(encoding), where encoding is the appropriate encoding. Python 2.x supported codecs are given here: Standard Encodings. Again, if you get UnicodeDecodeError then you’ve probably got the wrong encoding.

The meat of the sandwich

Work with Unicodes as you would normal strs.

Output

stdout / printing

print writes through the stdout stream. Python tries to configure an encoder on stdout so that Unicodes are encoded to the console’s encoding. For example, if a Linux shell’s locale is en_GB.UTF-8, the output will be encoded to UTF-8. On Windows, you will be limited to an 8bit code page.

An incorrectly configured console, such as corrupt locale, can lead to unexpected print errors. PYTHONIOENCODING environment variable can force the encoding for stdout.

Files

Just like input, io.open can be used to transparently convert Unicodes to encoded byte strings.

Database

The same configuration for reading will allow Unicodes to be written directly.

Python 3

Python 3 is no more Unicode capable than Python 2.x is, however it is slightly less confused on the topic. E.g the regular str is now a Unicode string and the old str is now bytes.

The default encoding is UTF-8, so if you .decode() a byte string without giving an encoding, Python 3 uses UTF-8 encoding. This probably fixes 50% of people’s Unicode problems.

Further, open() operates in text mode by default, so returns decoded str (Unicode ones). The encoding is derived from your locale, which tends to be UTF-8 on Un*x systems or an 8-bit code page, such as windows-1251, on Windows boxes.

Why you shouldn’t use sys.setdefaultencoding('utf8')

It’s a nasty hack (there’s a reason you have to use reload) that will only mask problems and hinder your migration to Python 3.x. Understand the problem, fix the root cause and enjoy Unicode zen. See Why should we NOT use sys.setdefaultencoding(“utf-8”) in a py script? for further details


回答 1

终于我明白了:

as3:/usr/local/lib/python2.7/site-packages# cat sitecustomize.py
# encoding=utf8  
import sys  

reload(sys)  
sys.setdefaultencoding('utf8')

让我检查一下:

as3:~/ngokevin-site# python
Python 2.7.6 (default, Dec  6 2013, 14:49:02)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.getdefaultencoding()
'utf8'
>>>

上面显示了python的默认编码为utf8。然后错误不再存在。

Finally I got it:

as3:/usr/local/lib/python2.7/site-packages# cat sitecustomize.py
# encoding=utf8  
import sys  

reload(sys)  
sys.setdefaultencoding('utf8')

Let me check:

as3:~/ngokevin-site# python
Python 2.7.6 (default, Dec  6 2013, 14:49:02)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.getdefaultencoding()
'utf8'
>>>

The above shows the default encoding of python is utf8. Then the error is no more.


回答 2

这是经典的“ unicode问题”。我相信解释这一点超出了StackOverflow答案的范围,无法完全解释正在发生的事情。

这里有很好的解释。

在非常简短的摘要中,您已经将某些内容解释为字节字符串,并将其解码为Unicode字符,但是默认编解码器(ascii)失败了。

我为您指出的演示文稿提供了避免这种情况的建议。使您的代码为“ unicode三明治”。在Python 2中,使用from __future__ import unicode_literals帮助。

更新:如何固定代码:

确定-在变量“源”中,您有一些字节。从您的问题中不清楚它们是如何到达的-也许您是从网络表单中读取它们的?无论如何,它们都不是用ascii编码的,但是python会假设它们是ASCII并尝试将它们转换为unicode。您需要明确告诉它编码是什么。这意味着您需要知道什么是编码!这并不总是那么容易,它完全取决于此字符串的来源。您可以尝试一些常见的编码-例如UTF-8。您将unicode()的编码作为第二个参数:

source = unicode(source, 'utf-8')

This is the classic “unicode issue”. I believe that explaining this is beyond the scope of a StackOverflow answer to completely explain what is happening.

It is well explained here.

In very brief summary, you have passed something that is being interpreted as a string of bytes to something that needs to decode it into Unicode characters, but the default codec (ascii) is failing.

The presentation I pointed you to provides advice for avoiding this. Make your code a “unicode sandwich”. In Python 2, the use of from __future__ import unicode_literals helps.

Update: how can the code be fixed:

OK – in your variable “source” you have some bytes. It is not clear from your question how they got in there – maybe you read them from a web form? In any case, they are not encoded with ascii, but python is trying to convert them to unicode assuming that they are. You need to explicitly tell it what the encoding is. This means that you need to know what the encoding is! That is not always easy, and it depends entirely on where this string came from. You could experiment with some common encodings – for example UTF-8. You tell unicode() the encoding as a second parameter:

source = unicode(source, 'utf-8')

回答 3

在某些情况下,当您检查默认编码(print sys.getdefaultencoding())时,它将返回您正在使用ASCII。如果更改为UTF-8,则无法使用,具体取决于变量的内容。我发现了另一种方法:

import sys
reload(sys)  
sys.setdefaultencoding('Cp1252')

In some cases, when you check your default encoding (print sys.getdefaultencoding()), it returns that you are using ASCII. If you change to UTF-8, it doesn’t work, depending on the content of your variable. I found another way:

import sys
reload(sys)  
sys.setdefaultencoding('Cp1252')

回答 4

我正在搜索以解决以下错误消息:

unicodedecodeerror:’ascii’编解码器无法解码位置5454的字节0xe2:序数不在范围内(128)

我终于通过指定’encoding’来解决它:

f = open('../glove/glove.6B.100d.txt', encoding="utf-8")

希望它能对您有所帮助。

I was searching to solve the following error message:

unicodedecodeerror: ‘ascii’ codec can’t decode byte 0xe2 in position 5454: ordinal not in range(128)

I finally got it fixed by specifying ‘encoding’:

f = open('../glove/glove.6B.100d.txt', encoding="utf-8")

Wish it could help you too.


回答 5

"UnicodeDecodeError: 'ascii' codec can't decode byte"

发生此错误的原因:input_string必须是unicode,但给出了str

"TypeError: Decoding Unicode is not supported"

发生此错误的原因:尝试将unicode input_string转换为unicode


因此,请首先检查您的input_string str是否为必需,并在必要时转换为unicode:

if isinstance(input_string, str):
   input_string = unicode(input_string, 'utf-8')

其次,以上内容仅更改类型,但不删除非ascii字符。如果要删除非ASCII字符:

if isinstance(input_string, str):
   input_string = input_string.decode('ascii', 'ignore').encode('ascii') #note: this removes the character and encodes back to string.

elif isinstance(input_string, unicode):
   input_string = input_string.encode('ascii', 'ignore')
"UnicodeDecodeError: 'ascii' codec can't decode byte"

Cause of this error: input_string must be unicode but str was given

"TypeError: Decoding Unicode is not supported"

Cause of this error: trying to convert unicode input_string into unicode


So first check that your input_string is str and convert to unicode if necessary:

if isinstance(input_string, str):
   input_string = unicode(input_string, 'utf-8')

Secondly, the above just changes the type but does not remove non ascii characters. If you want to remove non-ascii characters:

if isinstance(input_string, str):
   input_string = input_string.decode('ascii', 'ignore').encode('ascii') #note: this removes the character and encodes back to string.

elif isinstance(input_string, unicode):
   input_string = input_string.encode('ascii', 'ignore')

回答 6

我发现最好的方法是始终转换为unicode-但这很难实现,因为在实践中,您必须检查每个参数并将其转换为曾经编写的包括某种形式的字符串处理的每个函数和方法。

因此,我想出了以下方法来保证从任一输入的unicode或字节字符串。简而言之,请包含并使用以下lambda:

# guarantee unicode string
_u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t
_uu = lambda *tt: tuple(_u(t) for t in tt) 
# guarantee byte string in UTF8 encoding
_u8 = lambda t: t.encode('UTF-8', 'replace') if isinstance(t, unicode) else t
_uu8 = lambda *tt: tuple(_u8(t) for t in tt)

例子:

text='Some string with codes > 127, like Zürich'
utext=u'Some string with codes > 127, like Zürich'
print "==> with _u, _uu"
print _u(text), type(_u(text))
print _u(utext), type(_u(utext))
print _uu(text, utext), type(_uu(text, utext))
print "==> with u8, uu8"
print _u8(text), type(_u8(text))
print _u8(utext), type(_u8(utext))
print _uu8(text, utext), type(_uu8(text, utext))
# with % formatting, always use _u() and _uu()
print "Some unknown input %s" % _u(text)
print "Multiple inputs %s, %s" % _uu(text, text)
# but with string.format be sure to always work with unicode strings
print u"Also works with formats: {}".format(_u(text))
print u"Also works with formats: {},{}".format(*_uu(text, text))
# ... or use _u8 and _uu8, because string.format expects byte strings
print "Also works with formats: {}".format(_u8(text))
print "Also works with formats: {},{}".format(*_uu8(text, text))

这是关于此的更多原因

I find the best is to always convert to unicode – but this is difficult to achieve because in practice you’d have to check and convert every argument to every function and method you ever write that includes some form of string processing.

So I came up with the following approach to either guarantee unicodes or byte strings, from either input. In short, include and use the following lambdas:

# guarantee unicode string
_u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t
_uu = lambda *tt: tuple(_u(t) for t in tt) 
# guarantee byte string in UTF8 encoding
_u8 = lambda t: t.encode('UTF-8', 'replace') if isinstance(t, unicode) else t
_uu8 = lambda *tt: tuple(_u8(t) for t in tt)

Examples:

text='Some string with codes > 127, like Zürich'
utext=u'Some string with codes > 127, like Zürich'
print "==> with _u, _uu"
print _u(text), type(_u(text))
print _u(utext), type(_u(utext))
print _uu(text, utext), type(_uu(text, utext))
print "==> with u8, uu8"
print _u8(text), type(_u8(text))
print _u8(utext), type(_u8(utext))
print _uu8(text, utext), type(_uu8(text, utext))
# with % formatting, always use _u() and _uu()
print "Some unknown input %s" % _u(text)
print "Multiple inputs %s, %s" % _uu(text, text)
# but with string.format be sure to always work with unicode strings
print u"Also works with formats: {}".format(_u(text))
print u"Also works with formats: {},{}".format(*_uu(text, text))
# ... or use _u8 and _uu8, because string.format expects byte strings
print "Also works with formats: {}".format(_u8(text))
print "Also works with formats: {},{}".format(*_uu8(text, text))

Here’s some more reasoning about this.


回答 7

为了在Ubuntu安装中的操作系统级别解决此问题,请检查以下内容:

$ locale charmap

如果你得到

locale: Cannot set LC_CTYPE to default locale: No such file or directory

代替

UTF-8

然后设置LC_CTYPELC_ALL像这样:

$ export LC_ALL="en_US.UTF-8"
$ export LC_CTYPE="en_US.UTF-8"

In order to resolve this on an operating system level in an Ubuntu installation check the following:

$ locale charmap

If you get

locale: Cannot set LC_CTYPE to default locale: No such file or directory

instead of

UTF-8

then set LC_CTYPE and LC_ALL like this:

$ export LC_ALL="en_US.UTF-8"
$ export LC_CTYPE="en_US.UTF-8"

回答 8

编码将unicode对象转换为字符串对象。我认为您正在尝试对字符串对象进行编码。首先将结果转换为unicode对象,然后将该unicode对象编码为’utf-8’。例如

    result = yourFunction()
    result.decode().encode('utf-8')

Encode converts a unicode object in to a string object. I think you are trying to encode a string object. first convert your result into unicode object and then encode that unicode object into ‘utf-8’. for example

    result = yourFunction()
    result.decode().encode('utf-8')

回答 9

我遇到了同样的问题,但是它不适用于Python3。我遵循了这一点,它解决了我的问题:

enc = sys.getdefaultencoding()
file = open(menu, "r", encoding = enc)

读取/写入文件时,必须设置编码。

I had the same problem but it didn’t work for Python 3. I followed this and it solved my problem:

enc = sys.getdefaultencoding()
file = open(menu, "r", encoding = enc)

You have to set the encoding when you are reading/writing the file.


回答 10

有一个相同的错误,这解决了我的错误。谢谢!python 2和python 3在unicode处理方面的不同使腌制的文件与加载不兼容。因此,请使用python pickle的encoding参数。当我尝试从python 3.7中打开腌制数据时,下面的链接帮助我解决了类似的问题,而我的文件最初保存在python 2.x版本中。 https://blog.modest-destiny.com/posts/python-2-and-3-compatible-pickle-save-and-load/ 我在脚本中复制了load_pickle函数,并在加载我的脚本时调用了load_pickle(pickle_file)像这样的input_data:

input_data = load_pickle("my_dataset.pkl")

load_pickle函数在这里:

def load_pickle(pickle_file):
    try:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f)
    except UnicodeDecodeError as e:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f, encoding='latin1')
    except Exception as e:
        print('Unable to load data ', pickle_file, ':', e)
        raise
    return pickle_data

Got a same error and this solved my error. Thanks! python 2 and python 3 differing in unicode handling is making pickled files quite incompatible to load. So Use python pickle’s encoding argument. Link below helped me solve the similar problem when I was trying to open pickled data from my python 3.7, while my file was saved originally in python 2.x version. https://blog.modest-destiny.com/posts/python-2-and-3-compatible-pickle-save-and-load/ I copy the load_pickle function in my script and called the load_pickle(pickle_file) while loading my input_data like this:

input_data = load_pickle("my_dataset.pkl")

The load_pickle function is here:

def load_pickle(pickle_file):
    try:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f)
    except UnicodeDecodeError as e:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f, encoding='latin1')
    except Exception as e:
        print('Unable to load data ', pickle_file, ':', e)
        raise
    return pickle_data

回答 11

这为我工作:

    file = open('docs/my_messy_doc.pdf', 'rb')

This worked for me:

    file = open('docs/my_messy_doc.pdf', 'rb')

回答 12

简而言之,为了确保在Python 2中正确处理unicode:

  • 使用io.open读/写文件
  • 采用 from __future__ import unicode_literals
  • 配置其他数据输入/输出(例如数据库,网络)以使用unicode
  • 如果您无法将输出配置为utf-8,则将其转换为输出 print(text.encode('ascii', 'replace').decode())

有关说明,请参见@Alastair McCormack的详细答案

In short, to ensure proper unicode handling in Python 2:

  • use io.open for reading/writing files
  • use from __future__ import unicode_literals
  • configure other data inputs/outputs (e.g., databases, network) to use unicode
  • if you cannot configure outputs to utf-8, convert your output for them print(text.encode('ascii', 'replace').decode())

For explanations, see @Alastair McCormack’s detailed answer.


回答 13

我遇到相同的错误,URL包含非ascii字符(值大于128的字节),我的解决方案是:

url = url.decode('utf8').encode('utf-8')

注意:utf-8,utf8只是别名。仅使用’utf8’或’utf-8’应该以相同的方式工作

就我而言,对我有用,在Python 2.7中,我认为此分配更改了str内部表示形式中的“某些内容”,即,它强制对后备字节序列进行正确的解码,url最后将字符串放入utf-8中 str,所有的魔法都在正确的地方。Python中的Unicode对我来说是黑魔法。希望有用

I had the same error, with URLs containing non-ascii chars (bytes with values > 128), my solution:

url = url.decode('utf8').encode('utf-8')

Note: utf-8, utf8 are simply aliases . Using only ‘utf8’ or ‘utf-8’ should work in the same way

In my case, worked for me, in Python 2.7, I suppose this assignment changed ‘something’ in the str internal representation–i.e., it forces the right decoding of the backed byte sequence in url and finally puts the string into a utf-8 str with all the magic in the right place. Unicode in Python is black magic for me. Hope useful


回答 14

我遇到了字符串“PastelerÃaMallorca”相同的问题,并解决了:

unicode("Pastelería Mallorca", 'latin-1')

I got the same problem with the string “Pastelería Mallorca” and I solved with:

unicode("Pastelería Mallorca", 'latin-1')

回答 15

在Django(1.9.10)/ Python 2.7.5项目中,我经常遇到一些UnicodeDecodeErrorexceptions。主要是当我尝试将unicode字符串提供给日志记录时。我为任意对象创建了一个辅助函数,基本上将其格式化为8位ascii字符串,并将表中未包含的任何字符替换为’?’。我认为这不是最佳解决方案,但由于默认编码为ascii(并且我不想更改它),因此可以:

def encode_for_logging(c,encoding ='ascii'):
    如果isinstance(c,basestring):
        返回c.encode(encoding,'replace')
    elif isinstance(c,Iterable):
        c_ = []
        对于c中的v:
            c_.append(encode_for_logging(v,编码))
        返回c_
    其他:
        返回encode_for_logging(unicode(c))
`

In a Django (1.9.10)/Python 2.7.5 project I have frequent UnicodeDecodeError exceptions; mainly when I try to feed unicode strings to logging. I made a helper function for arbitrary objects to basically format to 8-bit ascii strings and replacing any characters not in the table to ‘?’. I think it’s not the best solution but since the default encoding is ascii (and i don’t want to change it) it will do:

def encode_for_logging(c, encoding='ascii'):
    if isinstance(c, basestring):
        return c.encode(encoding, 'replace')
    elif isinstance(c, Iterable):
        c_ = []
        for v in c:
            c_.append(encode_for_logging(v, encoding))
        return c_
    else:
        return encode_for_logging(unicode(c))
`

回答 16

当我们的字符串中包含一些非ASCII字符并且我们对该字符串执行任何操作而没有正确解码时,就会发生此错误。这帮助我解决了我的问题。我正在读取具有ID列,文本和解码字符的CSV文件,如下所示:

train_df = pd.read_csv("Example.csv")
train_data = train_df.values
for i in train_data:
    print("ID :" + i[0])
    text = i[1].decode("utf-8",errors="ignore").strip().lower()
    print("Text: " + text)

This error occurs when there are some non ASCII characters in our string and we are performing any operations on that string without proper decoding. This helped me solve my problem. I am reading a CSV file with columns ID,Text and decoding characters in it as below:

train_df = pd.read_csv("Example.csv")
train_data = train_df.values
for i in train_data:
    print("ID :" + i[0])
    text = i[1].decode("utf-8",errors="ignore").strip().lower()
    print("Text: " + text)

回答 17

这是我的解决方案,只需添加编码即可。 with open(file, encoding='utf8') as f

并且由于读取手套文件会花费很长时间,因此我建议将手套文件转换为numpy文件。当您使用netx时间阅读嵌入权重时,它将节省您的时间。

import numpy as np
from tqdm import tqdm


def load_glove(file):
    """Loads GloVe vectors in numpy array.
    Args:
        file (str): a path to a glove file.
    Return:
        dict: a dict of numpy arrays.
    """
    embeddings_index = {}
    with open(file, encoding='utf8') as f:
        for i, line in tqdm(enumerate(f)):
            values = line.split()
            word = ''.join(values[:-300])
            coefs = np.asarray(values[-300:], dtype='float32')
            embeddings_index[word] = coefs

    return embeddings_index

# EMBEDDING_PATH = '../embedding_weights/glove.840B.300d.txt'
EMBEDDING_PATH = 'glove.840B.300d.txt'
embeddings = load_glove(EMBEDDING_PATH)

np.save('glove_embeddings.npy', embeddings) 

要点链接:https : //gist.github.com/BrambleXu/634a844cdd3cd04bb2e3ba3c83aef227

Here is my solution, just add the encoding. with open(file, encoding='utf8') as f

And because reading glove file will take a long time, I recommend to the glove file to a numpy file. When netx time you read the embedding weights, it will save your time.

import numpy as np
from tqdm import tqdm


def load_glove(file):
    """Loads GloVe vectors in numpy array.
    Args:
        file (str): a path to a glove file.
    Return:
        dict: a dict of numpy arrays.
    """
    embeddings_index = {}
    with open(file, encoding='utf8') as f:
        for i, line in tqdm(enumerate(f)):
            values = line.split()
            word = ''.join(values[:-300])
            coefs = np.asarray(values[-300:], dtype='float32')
            embeddings_index[word] = coefs

    return embeddings_index

# EMBEDDING_PATH = '../embedding_weights/glove.840B.300d.txt'
EMBEDDING_PATH = 'glove.840B.300d.txt'
embeddings = load_glove(EMBEDDING_PATH)

np.save('glove_embeddings.npy', embeddings) 

Gist link: https://gist.github.com/BrambleXu/634a844cdd3cd04bb2e3ba3c83aef227


回答 18

在您的Python文件顶部指定:#encoding = utf-8,它应该可以解决此问题

Specify: # encoding= utf-8 at the top of your Python File, It should fix the issue


获取引起异常的异常描述和堆栈跟踪,全部作为字符串

问题:获取引起异常的异常描述和堆栈跟踪,全部作为字符串

我看过很多关于Python中堆栈跟踪和异常的文章。但是还没有找到我所需要的。

我有一段Python 2.7代码可能会引发异常。我想捕获它并将其完整描述和导致错误的堆栈跟踪分配给字符串(只是我们在控制台上看到的所有内容)。我需要此字符串以将其打印到GUI中的文本框中。

像这样:

try:
    method_that_can_raise_an_exception(params)
except Exception as e:
    print_to_textbox(complete_exception_description(e))

问题是:函数什么complete_exception_description

I’ve seen a lot of posts about stack trace and exceptions in Python. But haven’t found what I need.

I have a chunk of Python 2.7 code that may raise an exception. I would like to catch it and assign to a string its full description and the stack trace that caused the error (simply all we use to see on the console). I need this string to print it to a text box in the GUI.

Something like this:

try:
    method_that_can_raise_an_exception(params)
except Exception as e:
    print_to_textbox(complete_exception_description(e))

The problem is: what is the function complete_exception_description?


回答 0

请参阅traceback模块,特别是format_exc()功能。在这里

import traceback

try:
    raise ValueError
except ValueError:
    tb = traceback.format_exc()
else:
    tb = "No error"
finally:
    print tb

See the traceback module, specifically the format_exc() function. Here.

import traceback

try:
    raise ValueError
except ValueError:
    tb = traceback.format_exc()
else:
    tb = "No error"
finally:
    print tb

回答 1

让我们创建一个相当复杂的堆栈跟踪,以证明我们获得了完整的堆栈跟踪:

def raise_error():
    raise RuntimeError('something bad happened!')

def do_something_that_might_error():
    raise_error()

记录完整的堆栈跟踪

最佳做法是为模块设置一个记录器。它将知道模块的名称,并能够更改级别(在其他属性(例如处理程序)中)

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

我们可以使用此记录器来获取错误:

try:
    do_something_that_might_error()
except Exception as error:
    logger.exception(error)

哪个日志:

ERROR:__main__:something bad happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

因此,我们得到与发生错误时相同的输出:

>>> do_something_that_might_error()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

仅获取字符串

如果您真的只想要字符串,请改用traceback.format_exc函数,在此处演示如何记录字符串:

import traceback
try:
    do_something_that_might_error()
except Exception as error:
    just_the_string = traceback.format_exc()
    logger.debug(just_the_string)

哪个日志:

DEBUG:__main__:Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

Let’s create a decently complicated stacktrace, in order to demonstrate that we get the full stacktrace:

def raise_error():
    raise RuntimeError('something bad happened!')

def do_something_that_might_error():
    raise_error()

Logging the full stacktrace

A best practice is to have a logger set up for your module. It will know the name of the module and be able to change levels (among other attributes, such as handlers)

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

And we can use this logger to get the error:

try:
    do_something_that_might_error()
except Exception as error:
    logger.exception(error)

Which logs:

ERROR:__main__:something bad happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

And so we get the same output as when we have an error:

>>> do_something_that_might_error()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

Getting just the string

If you really just want the string, use the traceback.format_exc function instead, demonstrating logging the string here:

import traceback
try:
    do_something_that_might_error()
except Exception as error:
    just_the_string = traceback.format_exc()
    logger.debug(just_the_string)

Which logs:

DEBUG:__main__:Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

回答 2

对于Python 3,以下代码将Exception完全按照使用traceback.format_exc()以下命令获得的格式格式化对象:

import traceback

try: 
    method_that_can_raise_an_exception(params)
except Exception as ex:
    print(''.join(traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__)))

优点是仅Exception需要对象(由于记录的__traceback__属性),因此可以更轻松地将其作为参数传递给另一个函数以进行进一步处理。

With Python 3, the following code will format an Exception object exactly as would be obtained using traceback.format_exc():

import traceback

try: 
    method_that_can_raise_an_exception(params)
except Exception as ex:
    print(''.join(traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__)))

The advantage being that only the Exception object is needed (thanks to the recorded __traceback__ attribute), and can therefore be more easily passed as an argument to another function for further processing.


回答 3

>>> import sys
>>> import traceback
>>> try:
...   5 / 0
... except ZeroDivisionError as e:
...   type_, value_, traceback_ = sys.exc_info()
>>> traceback.format_tb(traceback_)
['  File "<stdin>", line 2, in <module>\n']
>>> value_
ZeroDivisionError('integer division or modulo by zero',)
>>> type_
<type 'exceptions.ZeroDivisionError'>
>>>
>>> 5 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

您使用sys.exc_info()来收集信息和traceback模块中的函数以对其进行格式化。 以下是一些格式化示例。

整个异常字符串位于:

>>> ex = traceback.format_exception(type_, value_, traceback_)
>>> ex
['Traceback (most recent call last):\n', '  File "<stdin>", line 2, in <module>\n', 'ZeroDivisionError: integer division or modulo by zero\n']
>>> import sys
>>> import traceback
>>> try:
...   5 / 0
... except ZeroDivisionError as e:
...   type_, value_, traceback_ = sys.exc_info()
>>> traceback.format_tb(traceback_)
['  File "<stdin>", line 2, in <module>\n']
>>> value_
ZeroDivisionError('integer division or modulo by zero',)
>>> type_
<type 'exceptions.ZeroDivisionError'>
>>>
>>> 5 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

You use sys.exc_info() to collect the information and the functions in the traceback module to format it. Here are some examples for formatting it.

The whole exception string is at:

>>> ex = traceback.format_exception(type_, value_, traceback_)
>>> ex
['Traceback (most recent call last):\n', '  File "<stdin>", line 2, in <module>\n', 'ZeroDivisionError: integer division or modulo by zero\n']

回答 4

对于那些使用Python-3的人

使用tracebackmodule和exception.__traceback__one可以提取堆栈跟踪,如下所示:

  • 使用获取当前的堆栈跟踪traceback.extract_stack()
  • 删除最后三个元素(因为那些是使我进入调试功能的堆栈中的条目)
  • __traceback__使用以下方法从异常对象追加traceback.extract_tb()
  • 使用格式化整个东西 traceback.format_list()
import traceback
def exception_to_string(excp):
   stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__)  # add limit=?? 
   pretty = traceback.format_list(stack)
   return ''.join(pretty) + '\n  {} {}'.format(excp.__class__,excp)

一个简单的演示:

def foo():
    try:
        something_invalid()
    except Exception as e:
        print(exception_to_string(e))

def bar():
    return foo()

调用时,将得到以下输出bar()

  File "./test.py", line 57, in <module>
    bar()
  File "./test.py", line 55, in bar
    return foo()
  File "./test.py", line 50, in foo
    something_invalid()

  <class 'NameError'> name 'something_invalid' is not defined

For those using Python-3

Using traceback module and exception.__traceback__ one can extract the stack-trace as follows:

  • grab the current stack-trace using traceback.extract_stack()
  • remove the last three elements (as those are entries in the stack that got me to my debug function)
  • append the __traceback__ from the exception object using traceback.extract_tb()
  • format the whole thing using traceback.format_list()
import traceback
def exception_to_string(excp):
   stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__)  # add limit=?? 
   pretty = traceback.format_list(stack)
   return ''.join(pretty) + '\n  {} {}'.format(excp.__class__,excp)

A simple demonstration:

def foo():
    try:
        something_invalid()
    except Exception as e:
        print(exception_to_string(e))

def bar():
    return foo()

We get the following output when we call bar():

  File "./test.py", line 57, in <module>
    bar()
  File "./test.py", line 55, in bar
    return foo()
  File "./test.py", line 50, in foo
    something_invalid()

  <class 'NameError'> name 'something_invalid' is not defined

回答 5

您可能还会考虑使用内置的Python模块cgitb来获取一些非常好且格式正确的异常信息,包括局部变量值,源代码上下文,函数参数等。

例如此代码…

import cgitb
cgitb.enable(format='text')

def func2(a, divisor):
    return a / divisor

def func1(a, b):
    c = b - 5
    return func2(a, c)

func1(1, 5)

我们得到这个异常输出…

ZeroDivisionError
Python 3.4.2: C:\tools\python\python.exe
Tue Sep 22 15:29:33 2015

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 c:\TEMP\cgittest2.py in <module>()
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
func1 = <function func1>

 c:\TEMP\cgittest2.py in func1(a=1, b=5)
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
global func2 = <function func2>
a = 1
c = 0

 c:\TEMP\cgittest2.py in func2(a=1, divisor=0)
    3
    4 def func2(a, divisor):
    5   return a / divisor
    6
    7 def func1(a, b):
a = 1
divisor = 0
ZeroDivisionError: division by zero
    __cause__ = None
    __class__ = <class 'ZeroDivisionError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of ZeroDivisionError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of ZeroDivisionError object>
    __doc__ = 'Second argument to a division or modulo operation was zero.'
    __eq__ = <method-wrapper '__eq__' of ZeroDivisionError object>
    __format__ = <built-in method __format__ of ZeroDivisionError object>
    __ge__ = <method-wrapper '__ge__' of ZeroDivisionError object>
    __getattribute__ = <method-wrapper '__getattribute__' of ZeroDivisionError object>
    __gt__ = <method-wrapper '__gt__' of ZeroDivisionError object>
    __hash__ = <method-wrapper '__hash__' of ZeroDivisionError object>
    __init__ = <method-wrapper '__init__' of ZeroDivisionError object>
    __le__ = <method-wrapper '__le__' of ZeroDivisionError object>
    __lt__ = <method-wrapper '__lt__' of ZeroDivisionError object>
    __ne__ = <method-wrapper '__ne__' of ZeroDivisionError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of ZeroDivisionError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of ZeroDivisionError object>
    __repr__ = <method-wrapper '__repr__' of ZeroDivisionError object>
    __setattr__ = <method-wrapper '__setattr__' of ZeroDivisionError object>
    __setstate__ = <built-in method __setstate__ of ZeroDivisionError object>
    __sizeof__ = <built-in method __sizeof__ of ZeroDivisionError object>
    __str__ = <method-wrapper '__str__' of ZeroDivisionError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ('division by zero',)
    with_traceback = <built-in method with_traceback of ZeroDivisionError object>

The above is a description of an error in a Python program.  Here is
the original traceback:

Traceback (most recent call last):
  File "cgittest2.py", line 11, in <module>
    func1(1, 5)
  File "cgittest2.py", line 9, in func1
    return func2(a, c)
  File "cgittest2.py", line 5, in func2
    return a / divisor
ZeroDivisionError: division by zero

You might also consider using the built-in Python module, cgitb, to get some really good, nicely formatted exception information including local variable values, source code context, function parameters etc..

For instance for this code…

import cgitb
cgitb.enable(format='text')

def func2(a, divisor):
    return a / divisor

def func1(a, b):
    c = b - 5
    return func2(a, c)

func1(1, 5)

we get this exception output…

ZeroDivisionError
Python 3.4.2: C:\tools\python\python.exe
Tue Sep 22 15:29:33 2015

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 c:\TEMP\cgittest2.py in <module>()
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
func1 = <function func1>

 c:\TEMP\cgittest2.py in func1(a=1, b=5)
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
global func2 = <function func2>
a = 1
c = 0

 c:\TEMP\cgittest2.py in func2(a=1, divisor=0)
    3
    4 def func2(a, divisor):
    5   return a / divisor
    6
    7 def func1(a, b):
a = 1
divisor = 0
ZeroDivisionError: division by zero
    __cause__ = None
    __class__ = <class 'ZeroDivisionError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of ZeroDivisionError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of ZeroDivisionError object>
    __doc__ = 'Second argument to a division or modulo operation was zero.'
    __eq__ = <method-wrapper '__eq__' of ZeroDivisionError object>
    __format__ = <built-in method __format__ of ZeroDivisionError object>
    __ge__ = <method-wrapper '__ge__' of ZeroDivisionError object>
    __getattribute__ = <method-wrapper '__getattribute__' of ZeroDivisionError object>
    __gt__ = <method-wrapper '__gt__' of ZeroDivisionError object>
    __hash__ = <method-wrapper '__hash__' of ZeroDivisionError object>
    __init__ = <method-wrapper '__init__' of ZeroDivisionError object>
    __le__ = <method-wrapper '__le__' of ZeroDivisionError object>
    __lt__ = <method-wrapper '__lt__' of ZeroDivisionError object>
    __ne__ = <method-wrapper '__ne__' of ZeroDivisionError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of ZeroDivisionError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of ZeroDivisionError object>
    __repr__ = <method-wrapper '__repr__' of ZeroDivisionError object>
    __setattr__ = <method-wrapper '__setattr__' of ZeroDivisionError object>
    __setstate__ = <built-in method __setstate__ of ZeroDivisionError object>
    __sizeof__ = <built-in method __sizeof__ of ZeroDivisionError object>
    __str__ = <method-wrapper '__str__' of ZeroDivisionError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ('division by zero',)
    with_traceback = <built-in method with_traceback of ZeroDivisionError object>

The above is a description of an error in a Python program.  Here is
the original traceback:

Traceback (most recent call last):
  File "cgittest2.py", line 11, in <module>
    func1(1, 5)
  File "cgittest2.py", line 9, in func1
    return func2(a, c)
  File "cgittest2.py", line 5, in func2
    return a / divisor
ZeroDivisionError: division by zero

回答 6

如果您希望在不处理异常的情况下获得相同的信息,则可以执行以下操作。这样做import traceback,然后:

try:
    ...
except Exception as e:
    print(traceback.print_tb(e.__traceback__))

我正在使用Python 3.7。

If you would like to get the same information given when an exception isn’t handled you can do something like this. Do import traceback and then:

try:
    ...
except Exception as e:
    print(traceback.print_tb(e.__traceback__))

I’m using Python 3.7.


回答 7

对于Python 3.5+

因此,您可以从您的异常以及其他任何异常中获取stacktrace。使用traceback.TracebackException它(只需更换ex您的除外):

print("".join(traceback.TracebackException.from_exception(ex).format())

一个扩展的示例和其他功能可以做到这一点:

import traceback

try:
    1/0
except Exception as ex:
    print("".join(traceback.TracebackException.from_exception(ex).format()) == traceback.format_exc() == "".join(traceback.format_exception(type(ex), ex, ex.__traceback__))) # This is True !!
    print("".join(traceback.TracebackException.from_exception(ex).format()))

输出将是这样的:

True
Traceback (most recent call last):
  File "untidsfsdfsdftled.py", line 29, in <module>
    1/0
ZeroDivisionError: division by zero

For Python 3.5+:

So, you can get the stacktrace from your exception as from any other exception. Use traceback.TracebackException for it (just replace ex with your exception):

print("".join(traceback.TracebackException.from_exception(ex).format())

An extended example and other features to do this:

import traceback

try:
    1/0
except Exception as ex:
    print("".join(traceback.TracebackException.from_exception(ex).format()) == traceback.format_exc() == "".join(traceback.format_exception(type(ex), ex, ex.__traceback__))) # This is True !!
    print("".join(traceback.TracebackException.from_exception(ex).format()))

The output will be something like this:

True
Traceback (most recent call last):
  File "untidsfsdfsdftled.py", line 29, in <module>
    1/0
ZeroDivisionError: division by zero

回答 8

我的2美分:

import sys, traceback
try: 
  ...
except Exception, e:
  T, V, TB = sys.exc_info()
  print ''.join(traceback.format_exception(T,V,TB))

my 2-cents:

import sys, traceback
try: 
  ...
except Exception, e:
  T, V, TB = sys.exc_info()
  print ''.join(traceback.format_exception(T,V,TB))

回答 9

如果您的目标是使异常和stacktrace消息看起来完全像python引发错误时一样,则以下内容在python 2 + 3中均适用:

import sys, traceback


def format_stacktrace():
    parts = ["Traceback (most recent call last):\n"]
    parts.extend(traceback.format_stack(limit=25)[:-2])
    parts.extend(traceback.format_exception(*sys.exc_info())[1:])
    return "".join(parts)

# EXAMPLE BELOW...

def a():
    b()


def b():
    c()


def c():
    d()


def d():
    assert False, "Noooh don't do it."


print("THIS IS THE FORMATTED STRING")
print("============================\n")

try:
    a()
except:
    stacktrace = format_stacktrace()
    print(stacktrace)

print("THIS IS HOW PYTHON DOES IT")
print("==========================\n")
a()

它通过format_stacktrace()从堆栈中删除最后一个调用并加入其余调用来工作。运行时,以上示例给出以下输出:

THIS IS THE FORMATTED STRING
============================

Traceback (most recent call last):
  File "test.py", line 31, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

THIS IS HOW PYTHON DOES IT
==========================

Traceback (most recent call last):
  File "test.py", line 38, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

If your goal is to make the exception and stacktrace message look exactly like when python throws an error, the following works in both python 2+3:

import sys, traceback


def format_stacktrace():
    parts = ["Traceback (most recent call last):\n"]
    parts.extend(traceback.format_stack(limit=25)[:-2])
    parts.extend(traceback.format_exception(*sys.exc_info())[1:])
    return "".join(parts)

# EXAMPLE BELOW...

def a():
    b()


def b():
    c()


def c():
    d()


def d():
    assert False, "Noooh don't do it."


print("THIS IS THE FORMATTED STRING")
print("============================\n")

try:
    a()
except:
    stacktrace = format_stacktrace()
    print(stacktrace)

print("THIS IS HOW PYTHON DOES IT")
print("==========================\n")
a()

It works by removing the last format_stacktrace() call from the stack and joining the rest. When run, the example above gives the following output:

THIS IS THE FORMATTED STRING
============================

Traceback (most recent call last):
  File "test.py", line 31, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

THIS IS HOW PYTHON DOES IT
==========================

Traceback (most recent call last):
  File "test.py", line 38, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

回答 10

我定义了以下帮助程序类:

import traceback
class TracedExeptions(object):
    def __init__(self):
        pass
    def __enter__(self):
        pass

    def __exit__(self, etype, value, tb):
      if value :
        if not hasattr(value, 'traceString'):
          value.traceString = "\n".join(traceback.format_exception(etype, value, tb))
        return False
      return True

我以后可以这样使用:

with TracedExeptions():
  #some-code-which-might-throw-any-exception

以后可以像这样消费它:

def log_err(ex):
  if hasattr(ex, 'traceString'):
    print("ERROR:{}".format(ex.traceString));
  else:
    print("ERROR:{}".format(ex));

(背景:我很沮丧,因为将Promises与s一起使用Exception,不幸的是将一个地方引发的异常传递给另一个地方的on_rejected处理程序,因此很难从原始位置进行回溯)

I defined following helper class:

import traceback
class TracedExeptions(object):
    def __init__(self):
        pass
    def __enter__(self):
        pass

    def __exit__(self, etype, value, tb):
      if value :
        if not hasattr(value, 'traceString'):
          value.traceString = "\n".join(traceback.format_exception(etype, value, tb))
        return False
      return True

Which I can later use like this:

with TracedExeptions():
  #some-code-which-might-throw-any-exception

And later can consume it like this:

def log_err(ex):
  if hasattr(ex, 'traceString'):
    print("ERROR:{}".format(ex.traceString));
  else:
    print("ERROR:{}".format(ex));

(Background: I was frustraded because of using Promises together with Exceptions, which unfortunately passes exceptions raised in one place to a on_rejected handler in another place, and thus it is difficult to get the traceback from original location)