分类目录归档:知识问答

什么是与Python 3等价的“ python -m SimpleHTTPServer”

问题:什么是与Python 3等价的“ python -m SimpleHTTPServer”

Python 3等效于python -m SimpleHTTPServer什么?

What is the Python 3 equivalent of python -m SimpleHTTPServer?


回答 0

文档

SimpleHTTPServer模块已合并到http.serverPython 3.0中。将源转换为3.0时,2to3工具将自动适应导入。

因此,您的命令是python -m http.server,或者取决于您的安装,它可以是:

python3 -m http.server

From the docs:

The SimpleHTTPServer module has been merged into http.server in Python 3.0. The 2to3 tool will automatically adapt imports when converting your sources to 3.0.

So, your command is python -m http.server, or depending on your installation, it can be:

python3 -m http.server

回答 1

等效为:

python3 -m http.server

The equivalent is:

python3 -m http.server

回答 2

使用2to3实用程序。

$ cat try.py
import SimpleHTTPServer

$ 2to3 try.py
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored try.py
--- try.py  (original)
+++ try.py  (refactored)
@@ -1 +1 @@
-import SimpleHTTPServer
+import http.server
RefactoringTool: Files that need to be modified:
RefactoringTool: try.py

Using 2to3 utility.

$ cat try.py
import SimpleHTTPServer

$ 2to3 try.py
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored try.py
--- try.py  (original)
+++ try.py  (refactored)
@@ -1 +1 @@
-import SimpleHTTPServer
+import http.server
RefactoringTool: Files that need to be modified:
RefactoringTool: try.py

回答 3

除了Petr的答案,如果您想绑定到特定接口而不是所有接口,则可以使用-b--bind标记。

python -m http.server 8000 --bind 127.0.0.1

上面的代码段应该可以解决问题。端口号8000。80用作HTTP通信的标准端口。

In addition to Petr’s answer, if you want to bind to a specific interface instead of all the interfaces you can use -b or --bind flag.

python -m http.server 8000 --bind 127.0.0.1

The above snippet should do the trick. 8000 is the port number. 80 is used as the standard port for HTTP communications.


回答 4

在我的一个项目中,我针对Python 2和3运行测试。为此,我编写了一个小脚本来独立启动本地服务器:

$ python -m $(python -c 'import sys; print("http.server" if sys.version_info[:2] > (2,7) else "SimpleHTTPServer")')
Serving HTTP on 0.0.0.0 port 8000 ...

作为别名:

$ alias serve="python -m $(python -c 'import sys; print("http.server" if sys.version_info[:2] > (2,7) else "SimpleHTTPServer")')"
$ serve
Serving HTTP on 0.0.0.0 port 8000 ...

请注意,我可以通过conda环境控制我的Python版本,因此可以python代替python3使用Python 3。

In one of my projects I run tests against Python 2 and 3. For that I wrote a small script which starts a local server independently:

$ python -m $(python -c 'import sys; print("http.server" if sys.version_info[:2] > (2,7) else "SimpleHTTPServer")')
Serving HTTP on 0.0.0.0 port 8000 ...

As an alias:

$ alias serve="python -m $(python -c 'import sys; print("http.server" if sys.version_info[:2] > (2,7) else "SimpleHTTPServer")')"
$ serve
Serving HTTP on 0.0.0.0 port 8000 ...

Please note that I control my Python version via conda environments, because of that I can use python instead of python3 for using Python 3.


Python类继承对象

问题:Python类继承对象

是否有理由要声明类object

我刚刚找到了执行此操作的代码,但找不到很好的理由。

class MyClass(object):
    # class code follows...

Is there any reason for a class declaration to inherit from object?

I just found some code that does this and I can’t find a good reason why.

class MyClass(object):
    # class code follows...

回答 0

是否有理由要声明类object

在Python 3中,除了Python 2和3之间的兼容性之外,没有任何理由。在Python 2中,原因很多


Python 2.x故事:

在Python 2.x(从2.2开始)中,根据是否存在object基类,有两种样式的类:

  1. “经典”样式类:它们没有object作为基类:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
  2. “新”样式类:它们具有直接或间接(例如,从内置类型继承)object作为基类:

    >>> class NewSpam(object):           # directly inherit from object
    ...    pass
    >>> NewSpam.__bases__
    (<type 'object'>,)
    >>> class IntSpam(int):              # indirectly inherit from object...
    ...    pass
    >>> IntSpam.__bases__
    (<type 'int'>,) 
    >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object  
    (<type 'object'>,)

毫无疑问,在编写一个类时,您总是想参加新式的类。这样做的好处很多,列举其中一些:

  • 支持描述符。具体而言,使用描述符使以下构造成为可能:

    1. classmethod:一种将类作为隐式参数(而不是实例)接收的方法。
    2. staticmethod:一种不将隐式参数self作为第一个参数的方法。
    3. 具有property以下属性:创建用于管理属性的获取,设置和删除的功能。
    4. __slots__:节省了类的内存消耗,还可以更快地访问属性。当然,它确实有局限性
  • __new__静态方法:让您自定义如何将新创建类的实例。

  • 方法解析顺序(MRO):尝试解析要调用的方法时,将以什么顺序搜索类的基类。

  • 与MRO有关,请super调用。另见,super()算超级。

如果您不继承object,请忘记这些。可以在此处找到对以前的要点以及“新”样式类的其他特权的更为详尽的描述。

新型类的缺点之一是,类本身对内存的要求更高。但是,除非您要创建许多类对象,否则我怀疑这将是一个问题,并且它是一个消极的消极情绪。


Python 3.x故事:

在Python 3中,一切都得到了简化。仅存在新样式的类(统称为类),因此添加的唯一区别object是要求您再输入8个字符。这个:

class ClassicSpam:
    pass

完全等效(除了它们的名称:-)与此:

class NewSpam(object):
     pass

并为此:

class Spam():
    pass

所有房间都object在他们的__bases__

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]

那你该怎么办?

在Python 2中: 始终object显式继承。享受津贴。

在Python 3中:object如果您要编写尝试与Python无关的代码,则继承自它,也就是说,它需要在Python 2和Python 3中均能正常工作。否则,实际上并没有什么不同,因为Python会为您插入代码在幕后。

Is there any reason for a class declaration to inherit from object?

In Python 3, apart from compatibility between Python 2 and 3, no reason. In Python 2, many reasons.


Python 2.x story:

In Python 2.x (from 2.2 onwards) there’s two styles of classes depending on the presence or absence of object as a base-class:

  1. “classic” style classes: they don’t have object as a base class:

    >>> class ClassicSpam:      # no base class
    ...     pass
    >>> ClassicSpam.__bases__
    ()
    
  2. “new” style classes: they have, directly or indirectly (e.g inherit from a built-in type), object as a base class:

    >>> class NewSpam(object):           # directly inherit from object
    ...    pass
    >>> NewSpam.__bases__
    (<type 'object'>,)
    >>> class IntSpam(int):              # indirectly inherit from object...
    ...    pass
    >>> IntSpam.__bases__
    (<type 'int'>,) 
    >>> IntSpam.__bases__[0].__bases__   # ... because int inherits from object  
    (<type 'object'>,)
    

Without a doubt, when writing a class you’ll always want to go for new-style classes. The perks of doing so are numerous, to list some of them:

  • Support for descriptors. Specifically, the following constructs are made possible with descriptors:

    1. classmethod: A method that receives the class as an implicit argument instead of the instance.
    2. staticmethod: A method that does not receive the implicit argument self as a first argument.
    3. properties with property: Create functions for managing the getting, setting and deleting of an attribute.
    4. __slots__: Saves memory consumptions of a class and also results in faster attribute access. Of course, it does impose limitations.
  • The __new__ static method: lets you customize how new class instances are created.

  • Method resolution order (MRO): in what order the base classes of a class will be searched when trying to resolve which method to call.

  • Related to MRO, super calls. Also see, super() considered super.

If you don’t inherit from object, forget these. A more exhaustive description of the previous bullet points along with other perks of “new” style classes can be found here.

One of the downsides of new-style classes is that the class itself is more memory demanding. Unless you’re creating many class objects, though, I doubt this would be an issue and it’s a negative sinking in a sea of positives.


Python 3.x story:

In Python 3, things are simplified. Only new-style classes exist (referred to plainly as classes) so, the only difference in adding object is requiring you to type in 8 more characters. This:

class ClassicSpam:
    pass

is completely equivalent (apart from their name :-) to this:

class NewSpam(object):
     pass

and to this:

class Spam():
    pass

All have object in their __bases__.

>>> [object in cls.__bases__ for cls in {Spam, NewSpam, ClassicSpam}]
[True, True, True]

So, what should you do?

In Python 2: always inherit from object explicitly. Get the perks.

In Python 3: inherit from object if you are writing code that tries to be Python agnostic, that is, it needs to work both in Python 2 and in Python 3. Otherwise don’t, it really makes no difference since Python inserts it for you behind the scenes.


回答 1

Python 3

  • class MyClass(object): =新型班
  • class MyClass:=新型类(隐式继承自object

Python 2

  • class MyClass(object): =新型班
  • class MyClass:= 老式类

说明

在Python 3.x中定义基类时,可以object从定义中删除。但是,这可以为严重难以跟踪的问题打开大门。

Python早在Python 2.2中就引入了新样式的类,而现在旧样式的类确实非常老。旧式类的讨论包含在2.x文档中,而在3.x文档中则不存在。

问题在于,Python 2.x中旧类的语法与Python 3.x中新类的替代语法相同。Python 2.x仍被广泛使用(例如GAE,Web2Py),并且任何代码(或编码器)在不经意间将3.x样式的类定义引入2.x代码中都会导致一些严重过时的基础对象。而且由于老式的类不在任何人的注意范围内,因此他们很可能不知道是什么打击了他们。

因此,只要把它弄清楚就行了,并省去一些2.x开发人员的眼泪。

Python 3

  • class MyClass(object): = New-style class
  • class MyClass: = New-style class (implicitly inherits from object)

Python 2

  • class MyClass(object): = New-style class
  • class MyClass: = OLD-STYLE CLASS

Explanation:

When defining base classes in Python 3.x, you’re allowed to drop the object from the definition. However, this can open the door for a seriously hard to track problem…

Python introduced new-style classes back in Python 2.2, and by now old-style classes are really quite old. Discussion of old-style classes is buried in the 2.x docs, and non-existent in the 3.x docs.

The problem is, the syntax for old-style classes in Python 2.x is the same as the alternative syntax for new-style classes in Python 3.x. Python 2.x is still very widely used (e.g. GAE, Web2Py), and any code (or coder) unwittingly bringing 3.x-style class definitions into 2.x code is going to end up with some seriously outdated base objects. And because old-style classes aren’t on anyone’s radar, they likely won’t know what hit them.

So just spell it out the long way and save some 2.x developer the tears.


回答 2

是的,这是一个“新样式”对象。这是python2.2中引入的功能。

新样式对象与经典对象具有不同的对象模型,并且某些内容无法与旧样式对象一起正常工作,例如和super()@property以及描述符。有关什么是新样式类的详细说明,请参见本文

SO链接描述了这些差异:Python中旧样式类和新样式类之间有什么区别?

Yes, this is a ‘new style’ object. It was a feature introduced in python2.2.

New style objects have a different object model to classic objects, and some things won’t work properly with old style objects, for instance, super(), @property and descriptors. See this article for a good description of what a new style class is.

SO link for a description of the differences: What is the difference between old style and new style classes in Python?


回答 3

难学Python的历史:

Python最初对类的再现在很多方面都被破坏了。到发现此故障时,已经为时已晚,他们必须予以支持。为了解决该问题,他们需要某种“新类”样式,以便“旧类”继续工作,但是您可以使用更正确的新版本。

他们决定使用小写的“对象”一词作为继承自您的“类”以构成一个类。这很令人困惑,但是一个类继承自名为“ object”的类来构成一个类,但它实际上并不是一个对象,而是一个类,但不要忘记从object继承。

也只是为了让您知道新样式类和旧样式类之间的区别是,新样式类始终从object类继承 或从另一个继承自的类继承object

class NewStyle(object):
    pass

另一个示例是:

class AnotherExampleOfNewStyle(NewStyle):
    pass

虽然老式的基类如下所示:

class OldStyle():
    pass

一个老式的子类如下所示:

class OldStyleSubclass(OldStyle):
    pass

您可以看到,Old Style基类不会从任何其他类继承,但是,Old Style类当然可以彼此继承。从对象继承可确保某些功能在每个Python类中均可用。Python 2.2中引入了新样式类

History from Learn Python the Hard Way:

Python’s original rendition of a class was broken in many serious ways. By the time this fault was recognized it was already too late, and they had to support it. In order to fix the problem, they needed some “new class” style so that the “old classes” would keep working but you can use the new more correct version.

They decided that they would use a word “object”, lowercased, to be the “class” that you inherit from to make a class. It is confusing, but a class inherits from the class named “object” to make a class but it’s not an object really its a class, but don’t forget to inherit from object.

Also just to let you know what the difference between new-style classes and old-style classes is, it’s that new-style classes always inherit from object class or from another class that inherited from object:

class NewStyle(object):
    pass

Another example is:

class AnotherExampleOfNewStyle(NewStyle):
    pass

While an old-style base class looks like this:

class OldStyle():
    pass

And an old-style child class looks like this:

class OldStyleSubclass(OldStyle):
    pass

You can see that an Old Style base class doesn’t inherit from any other class, however, Old Style classes can, of course, inherit from one another. Inheriting from object guarantees that certain functionality is available in every Python class. New style classes were introduced in Python 2.2


回答 4

是的,这是历史性的。没有它,它将创建一个老式的类。

如果type()在旧式对象上使用,则只会得到“实例”。在新型对象上,您可以得到其类。

Yes, it’s historical. Without it, it creates an old-style class.

If you use type() on an old-style object, you just get “instance”. On a new-style object you get its class.


回答 5

类创建语句的语法:

class <ClassName>(superclass):
    #code follows

如果没有您要特别继承的其他超类,则superclass始终应为object,这是Python中所有类的根。

object从技术上讲,它是Python中“新型”类的根。但是,如今的新型类与唯一的类一样好。

但是,如果您object在创建类时未明确使用该词,那么正如其他人提到的那样,Python 3.x隐式继承自object超类。但是我想显式总是比隐式好(地狱)

参考

The syntax of the class creation statement:

class <ClassName>(superclass):
    #code follows

In the absence of any other superclasses that you specifically want to inherit from, the superclass should always be object, which is the root of all classes in Python.

object is technically the root of “new-style” classes in Python. But the new-style classes today are as good as being the only style of classes.

But, if you don’t explicitly use the word object when creating classes, then as others mentioned, Python 3.x implicitly inherits from the object superclass. But I guess explicit is always better than implicit (hell)

Reference


将两个列表转换成字典

问题:将两个列表转换成字典

想象一下您有:

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']

产生以下字典的最简单方法是什么?

a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

Imagine that you have:

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']

What is the simplest way to produce the following dictionary?

a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

回答 0

像这样:

>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}

Voila :-)成对的dict构造函数和zip函数非常有用:https//docs.python.org/3/library/functions.html#func-dict

Like this:

>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}

Voila :-) The pairwise dict constructor and zip function are awesomely useful: https://docs.python.org/3/library/functions.html#func-dict


回答 1

想象一下您有:

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

产生以下字典的最简单方法是什么?

dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

绩效最高的dict构造函数zip

new_dict = dict(zip(keys, values))

在Python 3中,zip现在返回一个惰性迭代器,这是目前性能最高的方法。

dict(zip(keys, values))确实需要为dict和进行一次性全局查找zip,但它不会形成任何不必要的中间数据结构,也不必在函数应用程序中处理局部查找。

亚军,dict理解:

使用dict构造函数的第二名是使用dict理解的本机语法(而不是列表理解,因为其他人错误地将其理解为):

new_dict = {k: v for k, v in zip(keys, values)}

当您需要根据键或值进行映射或过滤时选择此选项。

在Python 2中,zip返回一个列表,以避免创建不必要的列表,请izip改用(别名为zip可以减少移至Python 3时的代码更改)。

from itertools import izip as zip

所以仍然是(2.7):

new_dict = {k: v for k, v in zip(keys, values)}

Python 2,非常适合<= 2.6

izipitertools变为zip在Python 3. izip大于拉链用于Python 2更好(因为它避免了不必要的列表创建),以及理想的2.6或以下:

from itertools import izip
new_dict = dict(izip(keys, values))

所有情况的结果:

在所有情况下:

>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}

说明:

如果我们查看帮助,dict就会发现它采用了多种形式的参数:


>>> help(dict)

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)

最佳方法是使用可迭代对象,同时避免创建不必要的数据结构。在Python 2中,zip创建了不必要的列表:

>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

在Python 3中,等效项为:

>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

Python 3 zip仅创建了一个可迭代的对象:

>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>

由于我们要避免创建不必要的数据结构,因此我们通常希望避免使用Python 2 zip(因为它创建了不必要的列表)。

性能较差的替代品:

这是一个传递给dict构造函数的生成器表达式:

generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)

或等效地:

dict((k, v) for k, v in zip(keys, values))

这是一个传递给dict构造函数的列表理解:

dict([(k, v) for k, v in zip(keys, values)])

在前两种情况下,在可迭代的zip上放置了一个额外的非操作(因此是不必要的)计算层,并且在列表理解的情况下,不必要地创建了一个额外的列表。我希望他们所有人的表现都不太好,当然也不会那么好。

绩效考核:

在Ubuntu 16.04上,由Nix提供的64位Python 3.8.2中,从最快到最慢的顺序是:

>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>> 
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583

dict(zip(keys, values)) 即使使用少量键和值也能获胜,但对于较大的键和值,则性能差异会更大。

评论者说:

min似乎是比较效果的一种坏方法。当然mean和/或max将是更有用的实际使用指标。

我们使用min这些算法是因为它们是确定性的。我们想知道算法在最佳条件下的性能。

如果操作系统由于任何原因挂起,则与我们要比较的内容无关,因此我们需要从分析中排除这些结果。

如果使用mean,这些事件将大大扭曲我们的结果,而如果使用,max我们将只会得到最极端的结果-最有可能受此类事件影响的结果。

评论者还说:

在python 3.6.8中,使用平均值,对dict的理解确实仍然更快,对于这些小列表而言,大约30%。对于较大的列表(10k个随机数),dict通话速度大约快10%。

我想我们的意思是dict(zip(...10k随机数。听起来确实是一个非常不寻常的用例。确实有道理,最直接的调用将在大型数据集中占主导地位,并且考虑到运行该测试将花费多长时间,进而使您的数字发生偏差,如果操作系统挂起占主导地位,我也不会感到惊讶。如果您使用meanmax我会认为您的结果毫无意义。

让我们在上面的示例中使用更实际的尺寸:

import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))

而且我们在这里看到,dict(zip(...对于较大的数据集,确实可以更快地运行约20%。

>>> min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)}))
9.698965263989521
>>> min(timeit.repeat(lambda: dict(zip(l1, l2))))
7.9965161079890095

Imagine that you have:

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

What is the simplest way to produce the following dictionary ?

dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

Most performant, dict constructor with zip

new_dict = dict(zip(keys, values))

In Python 3, zip now returns a lazy iterator, and this is now the most performant approach.

dict(zip(keys, values)) does require the one-time global lookup each for dict and zip, but it doesn’t form any unnecessary intermediate data-structures or have to deal with local lookups in function application.

Runner-up, dict comprehension:

A close runner-up to using the dict constructor is to use the native syntax of a dict comprehension (not a list comprehension, as others have mistakenly put it):

new_dict = {k: v for k, v in zip(keys, values)}

Choose this when you need to map or filter based on the keys or value.

In Python 2, zip returns a list, to avoid creating an unnecessary list, use izip instead (aliased to zip can reduce code changes when you move to Python 3).

from itertools import izip as zip

So that is still (2.7):

new_dict = {k: v for k, v in zip(keys, values)}

Python 2, ideal for <= 2.6

izip from itertools becomes zip in Python 3. izip is better than zip for Python 2 (because it avoids the unnecessary list creation), and ideal for 2.6 or below:

from itertools import izip
new_dict = dict(izip(keys, values))

Result for all cases:

In all cases:

>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}

Explanation:

If we look at the help on dict we see that it takes a variety of forms of arguments:


>>> help(dict)

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)

The optimal approach is to use an iterable while avoiding creating unnecessary data structures. In Python 2, zip creates an unnecessary list:

>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

In Python 3, the equivalent would be:

>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

and Python 3’s zip merely creates an iterable object:

>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>

Since we want to avoid creating unnecessary data structures, we usually want to avoid Python 2’s zip (since it creates an unnecessary list).

Less performant alternatives:

This is a generator expression being passed to the dict constructor:

generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)

or equivalently:

dict((k, v) for k, v in zip(keys, values))

And this is a list comprehension being passed to the dict constructor:

dict([(k, v) for k, v in zip(keys, values)])

In the first two cases, an extra layer of non-operative (thus unnecessary) computation is placed over the zip iterable, and in the case of the list comprehension, an extra list is unnecessarily created. I would expect all of them to be less performant, and certainly not more-so.

Performance review:

In 64 bit Python 3.8.2 provided by Nix, on Ubuntu 16.04, ordered from fastest to slowest:

>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>> 
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583

dict(zip(keys, values)) wins even with small sets of keys and values, but for larger sets, the differences in performance will become greater.

A commenter said:

min seems like a bad way to compare performance. Surely mean and/or max would be much more useful indicators for real usage.

We use min because these algorithms are deterministic. We want to know the performance of the algorithms under the best conditions possible.

If the operating system hangs for any reason, it has nothing to do with what we’re trying to compare, so we need to exclude those kinds of results from our analysis.

If we used mean, those kinds of events would skew our results greatly, and if we used max we will only get the most extreme result – the one most likely affected by such an event.

A commenter also says:

In python 3.6.8, using mean values, the dict comprehension is indeed still faster, by about 30% for these small lists. For larger lists (10k random numbers), the dict call is about 10% faster.

I presume we mean dict(zip(... with 10k random numbers. That does sound like a fairly unusual use case. It does makes sense that the most direct calls would dominate in large datasets, and I wouldn’t be surprised if OS hangs are dominating given how long it would take to run that test, further skewing your numbers. And if you use mean or max I would consider your results meaningless.

Let’s use a more realistic size on our top examples:

import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))

And we see here that dict(zip(... does indeed run faster for larger datasets by about 20%.

>>> min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)}))
9.698965263989521
>>> min(timeit.repeat(lambda: dict(zip(l1, l2))))
7.9965161079890095

回答 2

尝试这个:

>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}

在Python 2中,与相比,它在内存消耗方面更经济zip

Try this:

>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}

In Python 2, it’s also more economical in memory consumption compared to zip.


回答 3

>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}

回答 4

您还可以在≥2.7的Python中使用字典理解:

>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> {k: v for k, v in zip(keys, values)}
{'food': 'spam', 'age': 42, 'name': 'Monty'}

You can also use dictionary comprehensions in Python ≥ 2.7:

>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> {k: v for k, v in zip(keys, values)}
{'food': 'spam', 'age': 42, 'name': 'Monty'}

回答 5

一种更自然的方法是使用字典理解

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')    
dict = {keys[i]: values[i] for i in range(len(keys))}

A more natural way is to use dictionary comprehension

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')    
dict = {keys[i]: values[i] for i in range(len(keys))}

回答 6

如果需要在创建字典之前转换键或值,则可以使用生成器表达式。例:

>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3])) 

看看像Pythonista一样的代码:惯用Python

If you need to transform keys or values before creating a dictionary then a generator expression could be used. Example:

>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3])) 

Take a look Code Like a Pythonista: Idiomatic Python.


回答 7

使用Python 3.x进行dict理解

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

dic = {k:v for k,v in zip(keys, values)}

print(dic)

有关dict理解的更多信息,这里有一个示例:

>>> print {i : chr(65+i) for i in range(4)}
    {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}

with Python 3.x, goes for dict comprehensions

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

dic = {k:v for k,v in zip(keys, values)}

print(dic)

More on dict comprehensions here, an example is there:

>>> print {i : chr(65+i) for i in range(4)}
    {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}

回答 8

对于那些需要简单代码并且不熟悉的人zip

List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']

这可以通过一行代码来完成:

d = {List1[n]: List2[n] for n in range(len(List1))}

For those who need simple code and aren’t familiar with zip:

List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']

This can be done by one line of code:

d = {List1[n]: List2[n] for n in range(len(List1))}

回答 9

  • 2018-04-18

最好的解决方案仍然是:

In [92]: keys = ('name', 'age', 'food')
...: values = ('Monty', 42, 'spam')
...: 

In [93]: dt = dict(zip(keys, values))
In [94]: dt
Out[94]: {'age': 42, 'food': 'spam', 'name': 'Monty'}

整理一下:

    lst = [('name', 'Monty'), ('age', 42), ('food', 'spam')]
    keys, values = zip(*lst)
    In [101]: keys
    Out[101]: ('name', 'age', 'food')
    In [102]: values
    Out[102]: ('Monty', 42, 'spam')
  • 2018-04-18

The best solution is still:

In [92]: keys = ('name', 'age', 'food')
...: values = ('Monty', 42, 'spam')
...: 

In [93]: dt = dict(zip(keys, values))
In [94]: dt
Out[94]: {'age': 42, 'food': 'spam', 'name': 'Monty'}

Tranpose it:

    lst = [('name', 'Monty'), ('age', 42), ('food', 'spam')]
    keys, values = zip(*lst)
    In [101]: keys
    Out[101]: ('name', 'age', 'food')
    In [102]: values
    Out[102]: ('Monty', 42, 'spam')

回答 10

您可以使用以下代码:

dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))

但是请确保列表的长度相同。如果长度不相同,则zip函数会将较长的列表进行分类。

you can use this below code:

dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))

But make sure that length of the lists will be same.if length is not same.then zip function turncate the longer one.


回答 11

我在尝试解决与图形相关的问题时有这个疑问。我遇到的问题是我需要定义一个空的邻接列表,并想用一个空列表初始化所有节点,那是当我想到如何检查它是否足够快时,我的意思是说值得进行zip操作而不是简单的分配键值对。在大多数情况下,时间因素是重要的破冰者。因此,我对两种方法都执行了timeit操作。

import timeit
def dictionary_creation(n_nodes):
    dummy_dict = dict()
    for node in range(n_nodes):
        dummy_dict[node] = []
    return dummy_dict


def dictionary_creation_1(n_nodes):
    keys = list(range(n_nodes))
    values = [[] for i in range(n_nodes)]
    graph = dict(zip(keys, values))
    return graph


def wrapper(func, *args, **kwargs):
    def wrapped():
        return func(*args, **kwargs)
    return wrapped

iteration = wrapper(dictionary_creation, n_nodes)
shorthand = wrapper(dictionary_creation_1, n_nodes)

for trail in range(1, 8):
    print(f'Itertion: {timeit.timeit(iteration, number=trails)}\nShorthand: {timeit.timeit(shorthand, number=trails)}')

对于n_nodes = 10,000,000我得到了,

迭代:2.825081646999024速记:3.535717916001886

迭代:5.051560923002398速记:6.255070794999483

迭代:6.52859034499852速记:8.221581164998497

迭代:8.683652416999394速记:12.599181543999293

迭代:11.587241565001023速记:15.27298851100204

迭代:14.816342867001367速记:17.162912737003353

迭代:16.645022411001264速记:19.976680120998935

您可以清楚地看到在某一点之后,第n_步的迭代方法超过了第n-1_步的速记方法所花费的时间。

I had this doubt while I was trying to solve a graph-related problem. The issue I had was I needed to define an empty adjacency list and wanted to initialize all the nodes with an empty list, that’s when I thought how about I check if it is fast enough, I mean if it will be worth doing a zip operation rather than simple assignment key-value pair. After all most of the times, the time factor is an important ice breaker. So I performed timeit operation for both approaches.

import timeit
def dictionary_creation(n_nodes):
    dummy_dict = dict()
    for node in range(n_nodes):
        dummy_dict[node] = []
    return dummy_dict


def dictionary_creation_1(n_nodes):
    keys = list(range(n_nodes))
    values = [[] for i in range(n_nodes)]
    graph = dict(zip(keys, values))
    return graph


def wrapper(func, *args, **kwargs):
    def wrapped():
        return func(*args, **kwargs)
    return wrapped

iteration = wrapper(dictionary_creation, n_nodes)
shorthand = wrapper(dictionary_creation_1, n_nodes)

for trail in range(1, 8):
    print(f'Itertion: {timeit.timeit(iteration, number=trails)}\nShorthand: {timeit.timeit(shorthand, number=trails)}')

For n_nodes = 10,000,000 I get,

Iteration: 2.825081646999024 Shorthand: 3.535717916001886

Iteration: 5.051560923002398 Shorthand: 6.255070794999483

Iteration: 6.52859034499852 Shorthand: 8.221581164998497

Iteration: 8.683652416999394 Shorthand: 12.599181543999293

Iteration: 11.587241565001023 Shorthand: 15.27298851100204

Iteration: 14.816342867001367 Shorthand: 17.162912737003353

Iteration: 16.645022411001264 Shorthand: 19.976680120998935

You can clearly see after a certain point, iteration approach at n_th step overtakes the time taken by shorthand approach at n-1_th step.


回答 12

这也是在字典中添加列表值的示例

list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)

始终确保您的“键”(list1)始终在第一个参数中。

{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}

Here is also an example of adding a list value in you dictionary

list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)

always make sure the your “Key”(list1) is always in the first parameter.

{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}

回答 13

作为字典理解的解决方案,带有枚举:

dict = {item : values[index] for index, item in enumerate(keys)}

与枚举循环的解决方案:

dict = {}
for index, item in enumerate(keys):
    dict[item] = values[index]

Solution as dictionary comprehension with enumerate:

dict = {item : values[index] for index, item in enumerate(keys)}

Solution as for loop with enumerate:

dict = {}
for index, item in enumerate(keys):
    dict[item] = values[index]

回答 14

您也可以尝试将两个列表组合在一起的一个列表;)

a = [1,2,3,4]
n = [5,6,7,8]

x = []
for i in a,n:
    x.append(i)

print(dict(zip(x[0], x[1])))

You may also try with one list which is a combination of two lists ;)

a = [1,2,3,4]
n = [5,6,7,8]

x = []
for i in a,n:
    x.append(i)

print(dict(zip(x[0], x[1])))

回答 15

没有zip功能的方法

l1 = [1,2,3,4,5]
l2 = ['a','b','c','d','e']
d1 = {}
for l1_ in l1:
    for l2_ in l2:
        d1[l1_] = l2_
        l2.remove(l2_)
        break  

print (d1)


{1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}

method without zip function

l1 = [1,2,3,4,5]
l2 = ['a','b','c','d','e']
d1 = {}
for l1_ in l1:
    for l2_ in l2:
        d1[l1_] = l2_
        l2.remove(l2_)
        break  

print (d1)


{1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}

如何刷新打印功能的输出?

问题:如何刷新打印功能的输出?

如何强制将Python的打印功能输出到屏幕?

这与“ 禁用输出缓冲”不是重复的-链接的问题正在尝试无缓冲输出,尽管这更普遍。对于这个问题,最重要的答案太过强大或牵扯太多(对于这个问题,它们不是很好的答案),这个问题可以由相对新手在Google上找到。

How do I force Python’s print function to output to the screen?

This is not a duplicate of Disable output buffering – the linked question is attempting unbuffered output, while this is more general. The top answers in that question are too powerful or involved for this one (they’re not good answers for this), and this question can be found on Google by a relative newbie.


回答 0

在Python 3上,print可以采用可选flush参数

print("Hello world!", flush=True)

在Python 2上,您必须做

import sys
sys.stdout.flush()

打电话后print。默认情况下,print打印到sys.stdout(有关文件对象的更多信息,请参阅文档)。

On Python 3, print can take an optional flush argument

print("Hello world!", flush=True)

On Python 2 you’ll have to do

import sys
sys.stdout.flush()

after calling print. By default, print prints to sys.stdout (see the documentation for more about file objects).


回答 1

运行时python -h,我看到一个命令行选项

-u:无缓冲的二进制stdout和stderr; 也PYTHONUNBUFFERED = x有关与’-u’有关的内部缓冲的详细信息,请参见手册页

这是相关的文档

Running python -h, I see a command line option:

-u : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x see man page for details on internal buffering relating to ‘-u’

Here is the relevant doc.


回答 2

从Python 3.3开始,您可以强制使用普通print()函数进行刷新,而无需使用sys.stdout.flush(); 只需将“ flush”关键字参数设置为true。从文档中

print(* objects,sep =”,end =’\ n’,file = sys.stdout,flush = False)

将对象打印到流文件中,以sep分隔,然后以end分隔。sep,end和file(如果存在)必须作为关键字参数给出。

所有非关键字参数都将像str()一样转换为字符串,并写入流中,以sep分隔,然后以end分隔。sep和end都必须是字符串;它们也可以是None,这意味着要使用默认值。如果没有给出对象,print()只会写完。

file参数必须是带有write(string)方法的对象;如果不存在或没有,将使用sys.stdout。通常是否由文件决定是否对输出进行缓冲,但是如果flush关键字参数为true,则将强制刷新流。

Since Python 3.3, you can force the normal print() function to flush without the need to use sys.stdout.flush(); just set the “flush” keyword argument to true. From the documentation:

print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)

Print objects to the stream file, separated by sep and followed by end. sep, end and file, if present, must be given as keyword arguments.

All non-keyword arguments are converted to strings like str() does and written to the stream, separated by sep and followed by end. Both sep and end must be strings; they can also be None, which means to use the default values. If no objects are given, print() will just write end.

The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.


回答 3

如何刷新Python打印输出?

我建议这样做的五种方法:

  • 在Python 3中,调用print(..., flush=True)(flush参数在Python 2的print函数中不可用,并且print语句没有类似物)。
  • 调用file.flush()输出文件(我们可以包装python 2的print函数来执行此操作),例如,sys.stdout
  • 将此函数
    print = partial(print, flush=True)应用于局部函数的模块中的每个打印函数调用,并应用于全局模块。
  • -u通过传递给解释器命令的标志()将其应用于进程
  • 将其应用于您环境中的每个python进程PYTHONUNBUFFERED=TRUE(并取消设置变量以撤消此操作)。

Python 3.3以上

使用Python 3.3或更高版本,您可以仅flush=True将关键字参数提供给该print函数:

print('foo', flush=True) 

Python 2(或<3.3)

他们没有将flush参数反向移植到Python 2.7,因此,如果您使用的是Python 2(或低于3.3),并且想要与2和3都兼容的代码,我建议以下兼容代码。(请注意,__future__导入必须位于/非常靠近“ 模块顶部 ”):

from __future__ import print_function
import sys

if sys.version_info[:2] < (3, 3):
    old_print = print
    def print(*args, **kwargs):
        flush = kwargs.pop('flush', False)
        old_print(*args, **kwargs)
        if flush:
            file = kwargs.get('file', sys.stdout)
            # Why might file=None? IDK, but it works for print(i, file=None)
            file.flush() if file is not None else sys.stdout.flush()

上面的兼容性代码将涵盖大多数用途,但要进行更彻底的处理,请参阅six模块

另外,您也可以file.flush()在打印后调用,例如使用Python 2中的print语句:

import sys
print 'delayed output'
sys.stdout.flush()

将一个模块中的默认值更改为 flush=True

您可以通过在模块的全局范围内使用functools.partial来更改打印功能的默认值:

import functools
print = functools.partial(print, flush=True)

如果您看看我们新的部分函数,​​至少在Python 3中:

>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)

我们可以看到它的工作原理与正常情况一样:

>>> print('foo')
foo

实际上,我们可以覆盖新的默认值:

>>> print('foo', flush=False)
foo

再次注意,这只会更改当前的全局范围,因为当前全局范围内的打印名称将使内置print函数(如果在该当前全局范围中使用Python 2使用,则取消引用兼容性函数)。

如果要在函数内部而不是在模块的全局范围内执行此操作,则应给它取一个不同的名称,例如:

def foo():
    printf = functools.partial(print, flush=True)
    printf('print stuff like this')

如果在函数中将其声明为全局变量,则需要在模块的全局命名空间中对其进行更改,因此,应将其放在全局命名空间中,除非特定行为正是您想要的。

更改流程的默认值

我认为这里最好的选择是使用-u标志来获取无缓冲的输出。

$ python -u script.py

要么

$ python -um package.module

文档

强制stdin,stdout和stderr完全没有缓冲。在重要的系统上,还将stdin,stdout和stderr置于二进制模式。

请注意,file.readlines()和文件对象(sys.stdin中的行)具有内部缓冲,不受该选项的影响。要解决此问题,您将需要在while 1:循环内使用file.readline()。

更改Shell操作环境的默认值

如果将环境变量设置为非空字符串,则可以在环境或从该环境继承的环境中的所有python进程中获得以下行为:

例如,在Linux或OSX中:

$ export PYTHONUNBUFFERED=TRUE

或Windows:

C:\SET PYTHONUNBUFFERED=TRUE

文档

PYTHONUNBUFFERD

如果将其设置为非空字符串,则等效于指定-u选项。


附录

这是Python 2.7.12中的print函数的帮助-请注意没有 flush参数:

>>> from __future__ import print_function
>>> help(print)
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file: a file-like object (stream); defaults to the current sys.stdout.
    sep:  string inserted between values, default a space.
    end:  string appended after the last value, default a newline.

How to flush output of Python print?

I suggest five ways of doing this:

  • In Python 3, call print(..., flush=True) (the flush argument is not available in Python 2’s print function, and there is no analogue for the print statement).
  • Call file.flush() on the output file (we can wrap python 2’s print function to do this), for example, sys.stdout
  • apply this to every print function call in the module with a partial function,
    print = partial(print, flush=True) applied to the module global.
  • apply this to the process with a flag (-u) passed to the interpreter command
  • apply this to every python process in your environment with PYTHONUNBUFFERED=TRUE (and unset the variable to undo this).

Python 3.3+

Using Python 3.3 or higher, you can just provide flush=True as a keyword argument to the print function:

print('foo', flush=True) 

Python 2 (or < 3.3)

They did not backport the flush argument to Python 2.7 So if you’re using Python 2 (or less than 3.3), and want code that’s compatible with both 2 and 3, may I suggest the following compatibility code. (Note the __future__ import must be at/very “near the top of your module“):

from __future__ import print_function
import sys

if sys.version_info[:2] < (3, 3):
    old_print = print
    def print(*args, **kwargs):
        flush = kwargs.pop('flush', False)
        old_print(*args, **kwargs)
        if flush:
            file = kwargs.get('file', sys.stdout)
            # Why might file=None? IDK, but it works for print(i, file=None)
            file.flush() if file is not None else sys.stdout.flush()

The above compatibility code will cover most uses, but for a much more thorough treatment, see the six module.

Alternatively, you can just call file.flush() after printing, for example, with the print statement in Python 2:

import sys
print 'delayed output'
sys.stdout.flush()

Changing the default in one module to flush=True

You can change the default for the print function by using functools.partial on the global scope of a module:

import functools
print = functools.partial(print, flush=True)

if you look at our new partial function, at least in Python 3:

>>> print = functools.partial(print, flush=True)
>>> print
functools.partial(<built-in function print>, flush=True)

We can see it works just like normal:

>>> print('foo')
foo

And we can actually override the new default:

>>> print('foo', flush=False)
foo

Note again, this only changes the current global scope, because the print name on the current global scope will overshadow the builtin print function (or unreference the compatibility function, if using one in Python 2, in that current global scope).

If you want to do this inside a function instead of on a module’s global scope, you should give it a different name, e.g.:

def foo():
    printf = functools.partial(print, flush=True)
    printf('print stuff like this')

If you declare it a global in a function, you’re changing it on the module’s global namespace, so you should just put it in the global namespace, unless that specific behavior is exactly what you want.

Changing the default for the process

I think the best option here is to use the -u flag to get unbuffered output.

$ python -u script.py

or

$ python -um package.module

From the docs:

Force stdin, stdout and stderr to be totally unbuffered. On systems where it matters, also put stdin, stdout and stderr in binary mode.

Note that there is internal buffering in file.readlines() and File Objects (for line in sys.stdin) which is not influenced by this option. To work around this, you will want to use file.readline() inside a while 1: loop.

Changing the default for the shell operating environment

You can get this behavior for all python processes in the environment or environments that inherit from the environment if you set the environment variable to a nonempty string:

e.g., in Linux or OSX:

$ export PYTHONUNBUFFERED=TRUE

or Windows:

C:\SET PYTHONUNBUFFERED=TRUE

from the docs:

PYTHONUNBUFFERED

If this is set to a non-empty string it is equivalent to specifying the -u option.


Addendum

Here’s the help on the print function from Python 2.7.12 – note that there is no flush argument:

>>> from __future__ import print_function
>>> help(print)
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout)

    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file: a file-like object (stream); defaults to the current sys.stdout.
    sep:  string inserted between values, default a space.
    end:  string appended after the last value, default a newline.

回答 4

另外,如本博客中所建议,可以sys.stdout在无缓冲模式下重新打开:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

每个stdout.writeprint操作后自动刷新。

Also as suggested in this blog one can reopen sys.stdout in unbuffered mode:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

Each stdout.write and print operation will be automatically flushed afterwards.


回答 5

使用Python 3.x,该print()功能已扩展:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

因此,您可以执行以下操作:

print("Visiting toilet", flush=True)

Python文档条目

With Python 3.x the print() function has been extended:

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

So, you can just do:

print("Visiting toilet", flush=True)

Python Docs Entry


回答 6

使用-u命令行开关可以,但是有点笨拙。这意味着如果用户在没有-u选项的情况下调用脚本,程序可能会出现错误的行为。我通常使用custom stdout,例如:

class flushfile:
  def __init__(self, f):
    self.f = f

  def write(self, x):
    self.f.write(x)
    self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

…现在,您的所有print呼叫(sys.stdout隐式使用)将被自动flush编辑。

Using the -u command-line switch works, but it is a little bit clumsy. It would mean that the program would potentially behave incorrectly if the user invoked the script without the -u option. I usually use a custom stdout, like this:

class flushfile:
  def __init__(self, f):
    self.f = f

  def write(self, x):
    self.f.write(x)
    self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

… Now all your print calls (which use sys.stdout implicitly), will be automatically flushed.


回答 7

为什么不尝试使用未缓冲的文件?

f = open('xyz.log', 'a', 0)

要么

sys.stdout = open('out.log', 'a', 0)

Why not try using an unbuffered file?

f = open('xyz.log', 'a', 0)

OR

sys.stdout = open('out.log', 'a', 0)

回答 8

丹的想法不太有效:

#!/usr/bin/env python
class flushfile(file):
    def __init__(self, f):
        self.f = f
    def write(self, x):
        self.f.write(x)
        self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

print "foo"

结果:

Traceback (most recent call last):
  File "./passpersist.py", line 12, in <module>
    print "foo"
ValueError: I/O operation on closed file

我认为问题在于它是从文件类继承的,实际上是不必要的。根据sys.stdout的文档:

stdout和stderr不必是内置文件对象:任何对象都是可以接受的,只要它具有带有字符串参数的write()方法即可。

所以改变

class flushfile(file):

class flushfile(object):

使它工作正常。

Dan’s idea doesn’t quite work:

#!/usr/bin/env python
class flushfile(file):
    def __init__(self, f):
        self.f = f
    def write(self, x):
        self.f.write(x)
        self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

print "foo"

The result:

Traceback (most recent call last):
  File "./passpersist.py", line 12, in <module>
    print "foo"
ValueError: I/O operation on closed file

I believe the problem is that it inherits from the file class, which actually isn’t necessary. According to the docs for sys.stdout:

stdout and stderr needn’t be built-in file objects: any object is acceptable as long as it has a write() method that takes a string argument.

so changing

class flushfile(file):

to

class flushfile(object):

makes it work just fine.


回答 9

这是我的版本,它也提供writelines()和fileno():

class FlushFile(object):
    def __init__(self, fd):
        self.fd = fd

    def write(self, x):
        ret = self.fd.write(x)
        self.fd.flush()
        return ret

    def writelines(self, lines):
        ret = self.writelines(lines)
        self.fd.flush()
        return ret

    def flush(self):
        return self.fd.flush

    def close(self):
        return self.fd.close()

    def fileno(self):
        return self.fd.fileno()

Here is my version, which provides writelines() and fileno(), too:

class FlushFile(object):
    def __init__(self, fd):
        self.fd = fd

    def write(self, x):
        ret = self.fd.write(x)
        self.fd.flush()
        return ret

    def writelines(self, lines):
        ret = self.writelines(lines)
        self.fd.flush()
        return ret

    def flush(self):
        return self.fd.flush

    def close(self):
        return self.fd.close()

    def fileno(self):
        return self.fd.fileno()

回答 10

在Python 3中,您可以覆盖打印功能,默认设置为 flush = True

def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
    __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)

In Python 3 you can overwrite print function with default set to flush = True

def print(*objects, sep=' ', end='\n', file=sys.stdout, flush=True):
    __builtins__.print(*objects, sep=sep, end=end, file=file, flush=flush)

回答 11

我在Python 3.4中这样做:

'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')

I did it like this in Python 3.4:

'''To write to screen in real-time'''
message = lambda x: print(x, flush=True, end="")
message('I am flushing out now...')

回答 12

我首先努力了解冲洗选项的工作方式。我想做一个“加载显示”,这是我找到的解决方案:

for i in range(100000):
    print('{:s}\r'.format(''), end='', flush=True)
    print('Loading index: {:d}/100000'.format(i+1), end='')

第一行刷新先前的打印内容,第二行打印新的更新消息。我不知道这里是否存在单行语法。

I first struggled to understand how the flush option was working. I wanted to do a ‘loading display’ and here is the solution I found:

for i in range(100000):
    print('{:s}\r'.format(''), end='', flush=True)
    print('Loading index: {:d}/100000'.format(i+1), end='')

The first line flushes the previous print and the second line prints a new updated message. I don’t know if an one-line syntax exists here.


如何在Python中测量经过时间?

问题:如何在Python中测量经过时间?

我想要的是开始在我的代码中的某个地方开始计时,然后获取经过的时间,以衡量执行少量功能所花费的时间。我认为我使用的timeit模块错误,但是文档对我来说却很混乱。

import timeit

start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

What I want is to start counting time somewhere in my code and then get the passed time, to measure the time it took to execute few function. I think I’m using the timeit module wrong, but the docs are just confusing for me.

import timeit

start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

回答 0

如果您只想测量两点之间经过的挂钟时间,则可以使用 time.time()

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

这给出了执行时间(以秒为单位)。

自3.3起,另一个选择可能是使用perf_counterprocess_time,具体取决于您的要求。在3.3之前,建议使用time.clock(感谢Amber)。但是,目前不推荐使用:

在Unix上,以秒为单位返回当前处理器时间,以浮点数表示。精度,实际上是“处理器时间”含义的确切定义,取决于同名C函数的精度。

在Windows上,基于Win32函数,此函数返回自第一次调用此函数以来经过的时间(以秒为单位),以浮点数表示。 QueryPerformanceCounter()。分辨率通常优于一微秒。

从版本3.3开始不推荐使用:此功能的行为取决于平台:根据需要,使用perf_counter()process_time()相反,以具有明确定义的行为。

If you just want to measure the elapsed wall-clock time between two points, you could use time.time():

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

This gives the execution time in seconds.

Another option since 3.3 might be to use perf_counter or process_time, depending on your requirements. Before 3.3 it was recommended to use time.clock (thanks Amber). However, it is currently deprecated:

On Unix, return the current processor time as a floating point number expressed in seconds. The precision, and in fact the very definition of the meaning of “processor time”, depends on that of the C function of the same name.

On Windows, this function returns wall-clock seconds elapsed since the first call to this function, as a floating point number, based on the Win32 function QueryPerformanceCounter(). The resolution is typically better than one microsecond.

Deprecated since version 3.3: The behaviour of this function depends on the platform: use perf_counter() or process_time() instead, depending on your requirements, to have a well defined behaviour.


回答 1

使用timeit.default_timer代替timeit.timeit。前者会自动在您的平台和Python版本上提供最佳时钟:

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

根据操作系统,将timeit.default_timer分配给time.time()或time.clock()。在Python 3.3+ 上,在所有平台上,default_timertime.perf_counter()。参见Python-time.clock()与time.time()-准确性?

也可以看看:

Use timeit.default_timer instead of timeit.timeit. The former provides the best clock available on your platform and version of Python automatically:

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

timeit.default_timer is assigned to time.time() or time.clock() depending on OS. On Python 3.3+ default_timer is time.perf_counter() on all platforms. See Python – time.clock() vs. time.time() – accuracy?

See also:


回答 2

仅限Python 3:

由于从Python 3.3开始不推荐使用 time.clock(),因此您将希望time.perf_counter()用于系统范围的计时或time.process_time()进程范围的计时,就像您以前使用的方式一样time.clock()

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

新功能process_time将不包括睡眠期间经过的时间。

Python 3 only:

Since time.clock() is deprecated as of Python 3.3, you will want to use time.perf_counter() for system-wide timing, or time.process_time() for process-wide timing, just the way you used to use time.clock():

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

The new function process_time will not include time elapsed during sleep.


回答 3

有了您想计时的功能,

test.py:

def foo(): 
    # print "hello"   
    return "hello"

最简单的使用方法timeit是从命令行调用它:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

请勿尝试使用time.timetime.clock(天真)比较功能的速度。他们可能会产生误导性的结果

PS。不要将打印语句放在您希望计时的函数中;否则,测量的时间将取决于终端速度

Given a function you’d like to time,

test.py:

def foo(): 
    # print "hello"   
    return "hello"

the easiest way to use timeit is to call it from the command line:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

Do not try to use time.time or time.clock (naively) to compare the speed of functions. They can give misleading results.

PS. Do not put print statements in a function you wish to time; otherwise the time measured will depend on the speed of the terminal.


回答 4

使用上下文管理器执行此操作很有趣,该上下文管理器会自动记住进入with块时的开始时间,然后冻结块退出时的结束时间。只需一点技巧,您甚至可以通过相同的上下文管理器功能在块内获得运行时间计数。

核心库没有这个(但应该这样做)。放置到位后,您可以执行以下操作:

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

这是足以完成此任务的contextmanager代码:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

还有一些可运行的演示代码:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

请注意,根据该函数的设计,的退出值将elapsed()在块退出时冻结,并且进一步的调用将返回相同的持续时间(在此玩具示例中约为6秒)。

It’s fun to do this with a context-manager that automatically remembers the start time upon entry to a with block, then freezes the end time on block exit. With a little trickery, you can even get a running elapsed-time tally inside the block from the same context-manager function.

The core library doesn’t have this (but probably ought to). Once in place, you can do things like:

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

Here’s contextmanager code sufficient to do the trick:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

And some runnable demo code:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

Note that by design of this function, the return value of elapsed() is frozen on block exit, and further calls return the same duration (of about 6 seconds in this toy example).


回答 5

以秒为单位的测量时间

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

输出

0:00:01.946339

Measuring time in seconds:

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

Output:

0:00:01.946339

回答 6

我喜欢这个。timeitdoc太混乱了。

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

请注意,这里没有任何格式,我只是写到hh:mm:ss打印输出中,以便可以解释time_elapsed

I prefer this. timeit doc is far too confusing.

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

Note, that there isn’t any formatting going on here, I just wrote hh:mm:ss into the printout so one can interpret time_elapsed


回答 7

这是执行此操作的另一种方法:

>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.

与传统方式比较:

>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.

安装:

pip install pytictoc

有关更多详细信息,请参阅PyPi页面

Here’s another way to do this:

>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.

Comparing with traditional way:

>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.

Installation:

pip install pytictoc

Refer to the PyPi page for more details.


回答 8

这是我在这里经过许多不错的回答以及其他几篇文章后的发现。

首先,如果您在timeit和之间进行辩论time.time,则timeit有两个优点:

  1. timeit 选择操作系统和Python版本上可用的最佳计时器。
  2. timeit 禁用垃圾收集,但是,这不是您可能想要或不想要的东西。

现在的问题是,timeit使用起来并不是那么简单,因为它需要设置,并且当您进行大量导入时,情况变得很糟。理想情况下,您只需要一个装饰器或使用with块并测量时间。不幸的是,对此没有内置的功能,因此您有两个选择:

选项1:使用时间预算库

timebudget是一个多功能的,非常简单的库,你可以在一行代码只使用PIP后安装。

@timebudget  # Record how long this function takes
def my_method():
    # my code

选项2:直接使用代码模块

我在下面创建了小实用程序模块。

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f, no_print=False, disable_gc=False):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        if disable_gc:
            gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if disable_gc and gcold:
                gc.enable()
            if not no_print:
                print('"{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print=False, disable_gc=False):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        self.gcold = gc.isenabled()
        if self.disable_gc:
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

现在,您只需在其前面放置装饰器即可计时任何功能:

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

如果要计时部分代码,只需将其放在代码with块中:

import utils

#somewhere in my code

with utils.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

优点:

有几个半支持的版本,所以我想指出一些重点:

  1. 出于前面所述的原因,请使用timeit中的timer代替time.time。
  2. 如果需要,可以在计时期间禁用GC。
  3. 装饰器接受带有已命名或未命名参数的函数。
  4. 能够按块定时禁用打印(先使用with utils.MeasureBlockTime() as t,然后再使用t.elapsed)。
  5. 能够为块定时保持启用gc的能力。

Here are my findings after going through many good answers here as well as a few other articles.

First, if you are debating between timeit and time.time, the timeit has two advantages:

  1. timeit selects the best timer available on your OS and Python version.
  2. timeit disables garbage collection, however, this is not something you may or may not want.

Now the problem is that timeit is not that simple to use because it needs setup and things get ugly when you have a bunch of imports. Ideally, you just want a decorator or use with block and measure time. Unfortunately, there is nothing built-in available for this so you have two options:

Option 1: Use timebudget library

The timebudget is a versatile and very simple library that you can use just in one line of code after pip install.

@timebudget  # Record how long this function takes
def my_method():
    # my code

Option 2: Use code module directly

I created below little utility module.

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f, no_print=False, disable_gc=False):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        if disable_gc:
            gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if disable_gc and gcold:
                gc.enable()
            if not no_print:
                print('"{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print=False, disable_gc=False):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        self.gcold = gc.isenabled()
        if self.disable_gc:
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

Now you can time any function just by putting a decorator in front of it:

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

If you want to time portion of code then just put it inside with block:

import utils

#somewhere in my code

with utils.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

Advantages:

There are several half-backed versions floating around so I want to point out few highlights:

  1. Use timer from timeit instead of time.time for reasons described earlier.
  2. You can disable GC during timing if you want.
  3. Decorator accepts functions with named or unnamed params.
  4. Ability to disable printing in block timing (use with utils.MeasureBlockTime() as t and then t.elapsed).
  5. Ability to keep gc enabled for block timing.

回答 9

使用 time.time度量执行可以为您提供命令的整体执行时间,包括计算机上其他进程花费的运行时间。这是用户注意到的时间,但是如果您要比较不同的代码段/算法/函数/ …,则效果不佳。

有关更多信息timeit

如果您想对配置文件有更深入的了解:

更新:去年我大量使用了http://pythonhosted.org/line_profiler/,发现它非常有用,建议使用它代替Pythons profile模块。

Using time.time to measure execution gives you the overall execution time of your commands including running time spent by other processes on your computer. It is the time the user notices, but is not good if you want to compare different code snippets / algorithms / functions / …

More information on timeit:

If you want a deeper insight into profiling:

Update: I used http://pythonhosted.org/line_profiler/ a lot during the last year and find it very helpfull and recommend to use it instead of Pythons profile module.


回答 10

这是一个微小的计时器类,它返回“ hh:mm:ss”字符串:

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

用法:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

Here is a tiny timer class that returns “hh:mm:ss” string:

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

Usage:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

回答 11

python cProfile和pstats模块为测量某些功能所经过的时间提供了强大的支持,而无需在现有功能周围添加任何代码。

例如,如果您有python脚本timeFunctions.py:

import time

def hello():
    print "Hello :)"
    time.sleep(0.1)

def thankyou():
    print "Thank you!"
    time.sleep(0.05)

for idx in range(10):
    hello()

for idx in range(100):
    thankyou()

要运行事件探查器并为文件生成统计信息,您可以运行:

python -m cProfile -o timeStats.profile timeFunctions.py

这样做是使用cProfile模块来分析timeFunctions.py中的所有功能,并在timeStats.profile文件中收集统计信息。请注意,我们不必向现有模块(timeFunctions.py)添加任何代码,并且可以使用任何模块来完成此操作。

拥有stats文件后,您可以按以下方式运行pstats模块:

python -m pstats timeStats.profile

这将运行交互式统计浏览器,从而为您提供许多不错的功能。对于您的特定用例,您可以只检查功能的统计信息。在我们的示例中,检查这两个功能的统计信息显示以下内容:

Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'hello'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)

timeStats.profile% stats thankyou
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'thankyou'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)

这个虚拟的例子并没有做太多,但是让您知道可以做什么。关于这种方法的最好之处在于,我不必编辑任何现有代码即可获得这些数字,并且显然可以帮助进行性能分析。

The python cProfile and pstats modules offer great support for measuring time elapsed in certain functions without having to add any code around the existing functions.

For example if you have a python script timeFunctions.py:

import time

def hello():
    print "Hello :)"
    time.sleep(0.1)

def thankyou():
    print "Thank you!"
    time.sleep(0.05)

for idx in range(10):
    hello()

for idx in range(100):
    thankyou()

To run the profiler and generate stats for the file you can just run:

python -m cProfile -o timeStats.profile timeFunctions.py

What this is doing is using the cProfile module to profile all functions in timeFunctions.py and collecting the stats in the timeStats.profile file. Note that we did not have to add any code to existing module (timeFunctions.py) and this can be done with any module.

Once you have the stats file you can run the pstats module as follows:

python -m pstats timeStats.profile

This runs the interactive statistics browser which gives you a lot of nice functionality. For your particular use case you can just check the stats for your function. In our example checking stats for both functions shows us the following:

Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'hello'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)

timeStats.profile% stats thankyou
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'thankyou'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)

The dummy example does not do much but give you an idea of what can be done. The best part about this approach is that I dont have to edit any of my existing code to get these numbers and obviously help with profiling.


回答 12

这是另一个用于计时代码的上下文管理器-

用法:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

或者,如果您需要时间值

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

Benchmark.py

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

改编自http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html

Here’s another context manager for timing code –

Usage:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

or, if you need the time value

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

benchmark.py:

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

Adapted from http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html


回答 13

使用探查器模块。它提供了非常详细的配置文件。

import profile
profile.run('main()')

它输出类似:

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

我发现它非常有用。

Use profiler module. It gives a very detailed profile.

import profile
profile.run('main()')

it outputs something like:

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

I’ve found it very informative.


回答 14

我喜欢它简单(python 3):

from timeit import timeit

timeit(lambda: print("hello"))

单个执行的输出为微秒

2.430883963010274

说明:timeit 默认执行匿名函数一百万次,结果以秒为单位。因此,单次执行的结果是相同的数量,但平均为微秒


对于缓慢的操作添加较低数量的迭代,或者你可能会永远等待:

import time

timeit(lambda: time.sleep(1.5), number=1)

输出总是在数目迭代:

1.5015795179999714

I like it simple (python 3):

from timeit import timeit

timeit(lambda: print("hello"))

Output is microseconds for a single execution:

2.430883963010274

Explanation: timeit executes the anonymous function 1 million times by default and the result is given in seconds. Therefore the result for 1 single execution is the same amount but in microseconds on average.


For slow operations add a lower number of iterations or you could be waiting forever:

import time

timeit(lambda: time.sleep(1.5), number=1)

Output is always in seconds for the total number of iterations:

1.5015795179999714

回答 15

(仅对于Ipython)可以使用%timeit来衡量平均处理时间:

def foo():
    print "hello"

然后:

%timeit foo()

结果是这样的:

10000 loops, best of 3: 27 µs per loop

(With Ipython only) you can use %timeit to measure average processing time:

def foo():
    print "hello"

and then:

%timeit foo()

the result is something like:

10000 loops, best of 3: 27 µs per loop

回答 16

使用timeit的另一种方法:

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

One more way to use timeit:

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

回答 17

在python3上:

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

优雅而短暂。

on python3:

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

elegant and short.


回答 18

有点超级后来的反应,但也许对某人有用。我认为这是一种超级干净的方法。

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

请记住,“ print”是Python 3中的功能,而不是Python 2.7中的功能。但是,它可以与任何其他功能一起使用。干杯!

Kind of a super later response, but maybe it serves a purpose for someone. This is a way to do it which I think is super clean.

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

Keep in mind that “print” is a function in Python 3 and not Python 2.7. However, it works with any other function. Cheers!


回答 19

您可以使用timeit。

这是一个有关如何使用Python REPL测试带参数的naive_func的示例:

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

如果function没有任何参数,则不需要包装函数。

You can use timeit.

Here is an example on how to test naive_func that takes parameter using Python REPL:

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

You don’t need wrapper function if function doesn’t have any parameters.


回答 20

我们还可以将时间转换为人类可以理解的时间。

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')

We can also convert time into human-readable time.

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')

回答 21

我为此创建了一个库,如果您想测量一个函数,可以像这样做


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark

I made a library for this, if you want to measure a function you can just do it like this


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark


回答 22

要了解每个函数的递归调用,请执行以下操作:

%load_ext snakeviz
%%snakeviz

它只需在Jupyter笔记本中使用这两行代码,并生成一个漂亮的交互式图表。例如:

在此处输入图片说明

这是代码。再次,以2开头的%行是使用snakeviz所需的仅有的额外代码行:

# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib

%%snakeviz

files = glob.glob('*.txt')
def print_files_hashed(files):
    for file in files:
        with open(file) as f:
            print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)

在笔记本外运行snakeviz也似乎是可能的。在snakeviz网站上有更多信息。

To get insight on every function calls recursively, do:

%load_ext snakeviz
%%snakeviz

It just takes those 2 lines of code in a Jupyter notebook, and it generates a nice interactive diagram. For example:

enter image description here

Here is the code. Again, the 2 lines starting with % are the only extra lines of code needed to use snakeviz:

# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib

%%snakeviz

files = glob.glob('*.txt')
def print_files_hashed(files):
    for file in files:
        with open(file) as f:
            print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)

It also seems possible to run snakeviz outside notebooks. More info on the snakeviz website.


回答 23

import time

def getElapsedTime(startTime, units):
    elapsedInSeconds = time.time() - startTime
    if units == 'sec':
        return elapsedInSeconds
    if units == 'min':
        return elapsedInSeconds/60
    if units == 'hour':
        return elapsedInSeconds/(60*60)
import time

def getElapsedTime(startTime, units):
    elapsedInSeconds = time.time() - startTime
    if units == 'sec':
        return elapsedInSeconds
    if units == 'min':
        return elapsedInSeconds/60
    if units == 'hour':
        return elapsedInSeconds/(60*60)

回答 24

这种独特的基于类的方法提供了可打印的字符串表示形式,可自定义的舍入功能,并且可以方便地访问作为字符串或浮点数的经过时间。它是使用Python 3.7开发的。

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

用法:

# Setup timer
>>> timer = Timer()

# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.

# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425

This unique class-based approach offers a printable string representation, customizable rounding, and convenient access to the elapsed time as a string or a float. It was developed with Python 3.7.

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

Usage:

# Setup timer
>>> timer = Timer()

# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.

# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425

回答 25

测量小代码段的执行时间。

时间单位以秒为单位,以浮点数表示

import timeit
t = timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))')
t.timeit()
t.repeat()
>[1.2934070999999676, 1.3335035000000062, 1.422568500000125]

repeat()方法可以方便地多次调用timeit()并返回结果列表。

repeat(repeat=3

有了这个清单,我们可以花很多时间。

默认情况下,timeit()在计时期间临时关闭垃圾收集。time.Timer()解决了这个问题。

优点:

timeit.Timer()使独立计时更具可比性。gc可能是被测功能性能的重要组成部分。如果是这样,可以将gc(垃圾收集器)作为设置字符串中的第一条语句重新启用。例如:

timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))',setup='gc.enable()')

Python文档

Measure execution time of small code snippets.

Unit of time: measured in seconds as a float

import timeit
t = timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))')
t.timeit()
t.repeat()
>[1.2934070999999676, 1.3335035000000062, 1.422568500000125]

The repeat() method is a convenience to call timeit() multiple times and return a list of results.

repeat(repeat=3)¶

With this list we can take a mean of all times.

By default, timeit() temporarily turns off garbage collection during the timing. time.Timer() solves this problem.

Pros:

timeit.Timer() makes independent timings more comparable. The gc may be an important component of the performance of the function being measured. If so, gc(garbage collector) can be re-enabled as the first statement in the setup string. For example:

timeit.Timer('li = list(map(lambda x:x*2,[1,2,3,4,5]))',setup='gc.enable()')

Source Python Docs!


回答 26

如果您希望能够方便地计时功能,可以使用一个简单的装饰器:

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

您可以在想要计时的函数上使用它,如下所示:

@timing_decorator
def function_to_time():
    time.sleep(1)

然后function_to_time,在您每次调用时,它都会打印花费了多长时间以及函数的名称。

If you want to be able to time functions conveniently, you can use a simple decorator:

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

You can use it on a function that you want to time like this:

@timing_decorator
def function_to_time():
    time.sleep(1)

Then any time you call function_to_time, it will print how long it took and the name of the function being timed.


回答 27

基于https://stackoverflow.com/a/30024601/5095636提供的contextmanager解决方案,以下是lambda免费版本,因为flake8根据E731警告使用lambda :

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start_time = default_timer()

    class _Timer():
      start = start_time
      end = default_timer()
      duration = end - start

    yield _Timer

    end_time = default_timer()
    _Timer.end = end_time
    _Timer.duration = end_time - start_time

测试:

from time import sleep

with elapsed_timer() as t:
    print("start:", t.start)
    sleep(1)
    print("end:", t.end)

t.start
t.end
t.duration

based on the contextmanager solution given by https://stackoverflow.com/a/30024601/5095636, hereunder the lambda free version, as flake8 warns on the usage of lambda as per E731:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start_time = default_timer()

    class _Timer():
      start = start_time
      end = default_timer()
      duration = end - start

    yield _Timer

    end_time = default_timer()
    _Timer.end = end_time
    _Timer.duration = end_time - start_time

test:

from time import sleep

with elapsed_timer() as t:
    print("start:", t.start)
    sleep(1)
    print("end:", t.end)

t.start
t.end
t.duration

回答 28

我能想到的唯一方法是使用time.time()

import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)

希望对您有所帮助。

The only way I can think of is using time.time().

import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)

Hope that will help.


回答 29

timeit模块非常适合计时一小段Python代码。它至少可以以三种形式使用:

1-作为命令行模块

python2 -m timeit 'for i in xrange(10): oct(i)' 

2-对于短代码,请将其作为参数传递。

import timeit
timeit.Timer('for i in xrange(10): oct(i)').timeit()

3-对于更长的代码为:

import timeit
code_to_test = """
a = range(100000)
b = []
for i in a:
    b.append(i*2)
"""
elapsed_time = timeit.timeit(code_to_test, number=100)/100
print(elapsed_time)

The timeit module is good for timing a small piece of Python code. It can be used at least in three forms:

1- As a command-line module

python2 -m timeit 'for i in xrange(10): oct(i)' 

2- For a short code, pass it as arguments.

import timeit
timeit.Timer('for i in xrange(10): oct(i)').timeit()

3- For longer code as:

import timeit
code_to_test = """
a = range(100000)
b = []
for i in a:
    b.append(i*2)
"""
elapsed_time = timeit.timeit(code_to_test, number=100)/100
print(elapsed_time)

Python中的空对象?

问题:Python中的空对象?

如何在Python中引用null对象?

How do I refer to the null object in Python?


回答 0

在Python中,“空”对象是singleton None

检查事物是否为“无”的最好方法是使用身份运算符is

if foo is None:
    ...

In Python, the ‘null’ object is the singleton None.

The best way to check things for “Noneness” is to use the identity operator, is:

if foo is None:
    ...

回答 1

None,Python是否为空?

nullPython中没有,而是None。如前所述,测试是否已将某些None值作为值给出的最准确方法是使用is标识运算符,该运算符用于测试两个变量是否引用同一对象。

>>> foo is None
True
>>> foo = 'bar' 
>>> foo is None
False

基础

有并且只能是一个 None

None是该类的唯一实例,NoneType并且任何进一步实例化该类的尝试都将返回相同的对象,从而形成None单例。Python的新手经常会看到提到的错误消息,NoneType并想知道它是什么。我个人认为,这些消息仅可以None按名称提及,因为我们将很快看到,这None几乎没有歧义的余地。因此,如果您看到某些TypeError消息提到NoneType无法执行或无法执行该操作,则只知道它只是None被以一种无法使用的方式使用了。

另外,它None是一个内置常数,一旦您启动Python,它便可以在任何地方使用,无论是在模块,类还是函数中。NoneType相反,不是,您首先需要通过查询None其类来获取对其的引用。

>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType

您可以None使用Python的identity函数检查其唯一性id()。它返回分配给一个对象的唯一编号,每个对象都有一个。如果两个变量的id相同,则它们实际上指向同一对象。

>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000

None 不能覆盖

在Python的较旧版本(2.4之前)中,可以重新分配None,但现在不再可用。甚至不作为类属性或在函数范围内。

# In Python 2.7
>>> class SomeClass(object):
...     def my_fnc(self):
...             self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
        None = 'foo'
SyntaxError: cannot assign to None

# In Python 3.5
>>> class SomeClass:
...     def my_fnc(self):
...             self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
        None = 'foo'
SyntaxError: cannot assign to keyword

因此可以安全地假设所有None引用都是相同的。没有“风俗” None

测试操作员的None使用is

在编写代码时,您可能会想像这样来测试None

if value==None:
    pass

或者像这样测试虚假

if not value:
    pass

您需要了解其含义,以及为什么要明确地说明它通常是一个好主意。

情况1:测试值是否为 None

为什么这样做

value is None

而不是

value==None

第一个等效于:

id(value)==id(None)

而表达式value==None实际上是这样应用的

value.__eq__(None)

如果价值确实是,None那么您将得到期望的结果。

>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True

在大多数情况下,结果是相同的,但是该__eq__()方法打开了一扇门,使准确性的保证无效,因为可以在类中覆盖它以提供特殊的行为。

考虑这个类。

>>> class Empty(object):
...     def __eq__(self, other):
...         return not other

所以你试一下就None可以了

>>> empty = Empty()
>>> empty==None
True

但随后它也适用于空字符串

>>> empty==''
True

但是

>>> ''==None
False
>>> empty is None
False

情况2:None用作布尔值

以下两项测试

if value:
    # do something

if not value:
    # do something

实际上被评估为

if bool(value):
    # do something

if not bool(value):
    # do something

None是“ falsey”,表示如果将其强制转换为布尔值,它将返回False,如果应用了not运算符,它将返回True。但是请注意,它不是唯一的属性None。除了False本身之外,该属性还由空列表,元组,集合,字典,字符串以及0以及实现__bool__()magic方法的类中的所有对象共享来共享False

>>> bool(None)
False
>>> not None
True

>>> bool([])
False
>>> not []
True

>>> class MyFalsey(object):
...     def __bool__(self):
...         return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True

因此,当以以下方式测试变量时,请特别注意要包含或排除的内容:

def some_function(value=None):
    if not value:
        value = init_value()

在上面,您是要init_value()在将值专门设置为时调用None,还是要将值设置为0,空字符串或空列表也触发初始化。就像我说的,要注意。通常在Python中,显式要比隐式好

None 在实践中

None 用作信号值

None在Python中具有特殊的地位。这是最喜欢的基准值,因为许多算法将其视为特殊值。在这种情况下,它可以用作标志,以表明某种情况需要某种特殊处理(例如,设置默认值)。

您可以分配None给函数的关键字参数,然后对其进行显式测试。

def my_function(value, param=None):
    if param is None:
        # do something outrageous!

尝试获取对象的属性时,可以将其作为默认值返回,然后在执行特殊操作之前对其进行显式测试。

value = getattr(some_obj, 'some_attribute', None)
if value is None:
    # do something spectacular!

默认情况下,尝试访问不存在的键时,字典的get()方法返回None

>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True

如果您尝试使用下标符号访问它,KeyError则会引发a

>>> value = some_dict['foo']
KeyError: 'foo'

同样,如果您尝试弹出一个不存在的项目

>>> value = some_dict.pop('foo')
KeyError: 'foo'

您可以使用通常设置为的默认值来抑制 None

value = some_dict.pop('foo', None)
if value is None:
    # booom!

None 用作标志和有效值

None当它不被视为有效值,而更像是执行某些特殊操作的信号时,上面描述的apply 用法。但是,在某些情况下,有时重要的是知道None来自哪里,因为即使将其用作信号,它也可能是数据的一部分。

当您查询对象以getattr(some_obj, 'attribute_name', None)获取其属性时,None它不会告诉您您尝试访问的属性是否设置为None对象,或者对象是否完全不存在。从字典访问密钥的情况相同,例如some_dict.get('some_key'),您不知道它some_dict['some_key']是否丢失了,或者只是将其设置为None。如果您需要这些信息,通常的处理方法是直接尝试从try/except构造中访问属性或键:

try:
    # equivalent to getattr() without specifying a default
    # value = getattr(some_obj, 'some_attribute')
    value = some_obj.some_attribute
    # now you handle `None` the data here
    if value is None:
        # do something here because the attribute was set to None
except AttributeError:
    # we're now hanling the exceptional situation from here.
    # We could assign None as a default value if required.
    value = None 
    # In addition, since we now know that some_obj doesn't have the
    # attribute 'some_attribute' we could do something about that.
    log_something(some_obj)

与dict类似:

try:
    value = some_dict['some_key']
    if value is None:
        # do something here because 'some_key' is set to None
except KeyError:
    # set a default 
    value = None
    # and do something because 'some_key' was missing
    # from the dict.
    log_something(some_dict)

上面的两个示例显示了如何处理对象和字典的情况,函数呢?同样,但为此我们使用了double asterisks关键字参数:

def my_function(**kwargs):
    try:
        value = kwargs['some_key'] 
        if value is None:
            # do something because 'some_key' is explicitly 
            # set to None
    except KeyError:
        # we assign the default
        value = None
        # and since it's not coming from the caller.
        log_something('did not receive "some_key"')

None 仅用作有效值

如果您发现您的代码中散布着上述try/except模式,只是为了区分None标志和None数据,则只需使用另一个测试值即可。有一种模式是,将超出有效值集的值作为数据的一部分插入数据结构中,并用于控制和测试特殊条件(例如边界,状态等)。这样的值称为哨兵,可以将其用作None信号。在Python中创建一个哨兵很简单。

undefined = object()

undefined上面的对象是唯一的,并且不执行任何程序可能感兴趣的任何事情,因此,它是None作为flag 的绝佳替代品。一些注意事项适用,有关代码之后的更多说明。

具有功能

def my_function(value, param1=undefined, param2=undefined):
    if param1 is undefined:
        # we know nothing was passed to it, not even None
        log_something('param1 was missing')
        param1 = None


    if param2 is undefined:
        # we got nothing here either
        log_something('param2 was missing')
        param2 = None

与字典

value = some_dict.get('some_key', undefined)
if value is None:
    log_something("'some_key' was set to None")

if value is undefined:
    # we know that the dict didn't have 'some_key'
    log_something("'some_key' was not set at all")
    value = None

带物体

value = getattr(obj, 'some_attribute', undefined) 
if value is None:
    log_something("'obj.some_attribute' was set to None")
if value is undefined:
    # we know that there's no obj.some_attribute
    log_something("no 'some_attribute' set on obj")
    value = None

正如我之前提到的,自定义哨兵带有一些警告。首先,它们不是类似的关键字None,因此python不能保护它们。您可以undefined随时在定义的模块中的任何位置覆盖上面的内容,因此请谨慎使用它们。接下来,by返回的实例object()不是单例,如果您进行10次该调用,则会得到10个不同的对象。最后,哨兵的使用是高度特质的。前哨特定于它所使用的库,因此,其范围通常应限于库的内部。它不应该“泄漏”出去。仅当外部代码的目的是扩展或补充库的API时,外部代码才应意识到这一点。

None, Python’s null?

There’s no null in Python, instead there’s None. As stated already the most accurate way to test that something has been given None as a value is to use the is identity operator, which tests that two variables refer to the same object.

>>> foo is None
True
>>> foo = 'bar' 
>>> foo is None
False

The basics

There is and can only be one None

None is the sole instance of the class NoneType and any further attempts at instantiating that class will return the same object, which makes None a singleton. Newcomers to Python often see error messages that mention NoneType and wonder what it is. It’s my personal opinion that these messages could simply just mention None by name because, as we’ll see shortly, None leaves little room to ambiguity. So if you see some TypeError message that mentions that NoneType can’t do this or can’t do that, just know that it’s simply the one None that was being used in a way that it can’t.

Also, None is a built-in constant, as soon as you start Python it’s available to use from everywhere, whether in module, class, or function. NoneType by contrast is not, you’d need to get a reference to it first by querying None for its class.

>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType

You can check None‘s uniqueness with Python’s identity function id(). It returns the unique number assigned to an object, each object has one. If the id of two variables is the same, then they point in fact to the same object.

>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000

None cannot be overwritten

In much older version of Python (before 2.4) it was possible to reassign None, but not anymore. Not even as a class attribute or in the confines of a function.

# In Python 2.7
>>> class SomeClass(object):
...     def my_fnc(self):
...             self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
        None = 'foo'
SyntaxError: cannot assign to None

# In Python 3.5
>>> class SomeClass:
...     def my_fnc(self):
...             self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
        None = 'foo'
SyntaxError: cannot assign to keyword

It’s therefore safe to assume that all None references are the same. There’s no “custom” None.

To test for None use the is operator

When writing code you might be tempted to test for Noneness like this:

if value==None:
    pass

Or to test for falsehood like this

if not value:
    pass

You need to understand the implications and why it’s often a good idea to be explicit.

Case 1: testing if a value is None

why do this

value is None

rather than

value==None

The first is equivalent to:

id(value)==id(None)

Whereas the expression value==None is in fact applied like this

value.__eq__(None)

if the value really is None then you’ll get what you expected.

>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True

In most common cases the outcome will be the same, but the __eq__() method opens a door that voids any guarantee of accuracy, since it can be overridden in a class to provide special behavior.

Consider this class.

>>> class Empty(object):
...     def __eq__(self, other):
...         return not other

So you try it on None and it works

>>> empty = Empty()
>>> empty==None
True

But then it also works on the empty string

>>> empty==''
True

And yet

>>> ''==None
False
>>> empty is None
False

Case 2: Using None as a boolean

The following two tests

if value:
    # do something

if not value:
    # do something

are in fact evaluated as

if bool(value):
    # do something

if not bool(value):
    # do something

None is a “falsey”, meaning that if cast to a boolean it will return False and if applied the not operator it will return True. Note however that it’s not a property unique to None. In addition to False itself, the property is shared by empty lists, tuples, sets, dicts, strings, as well as 0, and all objects from classes that implement the __bool__() magic method to return False.

>>> bool(None)
False
>>> not None
True

>>> bool([])
False
>>> not []
True

>>> class MyFalsey(object):
...     def __bool__(self):
...         return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True

So when testing for variables in the following way, be extra aware of what you’re including or excluding from the test:

def some_function(value=None):
    if not value:
        value = init_value()

In the above, did you mean to call init_value() when the value is set specifically to None, or did you mean that a value set to 0, or the empty string, or an empty list should also trigger the initialization. Like I said, be mindful. As it’s often the case in Python explicit is better than implicit.

None in practice

None used as a signal value

None has a special status in Python. It’s a favorite baseline value because many algorithms treat it as an exceptional value. In such scenarios it can be used as a flag to signal that a condition requires some special handling (such as the setting of a default value).

You can assign None to the keyword arguments of a function and then explicitly test for it.

def my_function(value, param=None):
    if param is None:
        # do something outrageous!

You can return it as the default when trying to get to an object’s attribute and then explicitly test for it before doing something special.

value = getattr(some_obj, 'some_attribute', None)
if value is None:
    # do something spectacular!

By default a dictionary’s get() method returns None when trying to access a non-existing key:

>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True

If you were to try to access it by using the subscript notation a KeyError would be raised

>>> value = some_dict['foo']
KeyError: 'foo'

Likewise if you attempt to pop a non-existing item

>>> value = some_dict.pop('foo')
KeyError: 'foo'

which you can suppress with a default value that is usually set to None

value = some_dict.pop('foo', None)
if value is None:
    # booom!

None used as both a flag and valid value

The above described uses of None apply when it is not considered a valid value, but more like a signal to do something special. There are situations however where it sometimes matters to know where None came from because even though it’s used as a signal it could also be part of the data.

When you query an object for its attribute with getattr(some_obj, 'attribute_name', None) getting back None doesn’t tell you if the attribute you were trying to access was set to None or if it was altogether absent from the object. Same situation when accessing a key from a dictionary like some_dict.get('some_key'), you don’t know if some_dict['some_key'] is missing or if it’s just set to None. If you need that information, the usual way to handle this is to directly attempt accessing the attribute or key from within a try/except construct:

try:
    # equivalent to getattr() without specifying a default
    # value = getattr(some_obj, 'some_attribute')
    value = some_obj.some_attribute
    # now you handle `None` the data here
    if value is None:
        # do something here because the attribute was set to None
except AttributeError:
    # we're now hanling the exceptional situation from here.
    # We could assign None as a default value if required.
    value = None 
    # In addition, since we now know that some_obj doesn't have the
    # attribute 'some_attribute' we could do something about that.
    log_something(some_obj)

Similarly with dict:

try:
    value = some_dict['some_key']
    if value is None:
        # do something here because 'some_key' is set to None
except KeyError:
    # set a default 
    value = None
    # and do something because 'some_key' was missing
    # from the dict.
    log_something(some_dict)

The above two examples show how to handle object and dictionary cases, what about functions? Same thing, but we use the double asterisks keyword argument to that end:

def my_function(**kwargs):
    try:
        value = kwargs['some_key'] 
        if value is None:
            # do something because 'some_key' is explicitly 
            # set to None
    except KeyError:
        # we assign the default
        value = None
        # and since it's not coming from the caller.
        log_something('did not receive "some_key"')

None used only as a valid value

If you find that your code is littered with the above try/except pattern simply to differentiate between None flags and None data, then just use another test value. There’s a pattern where a value that falls outside the set of valid values is inserted as part of the data in a data structure and is used to control and test special conditions (e.g. boundaries, state, etc). Such a value is called a sentinel and it can be used the way None is used as a signal. It’s trivial to create a sentinel in Python.

undefined = object()

The undefined object above is unique and doesn’t do much of anything that might be of interest to a program, it’s thus an excellent replacement for None as a flag. Some caveats apply, more about that after the code.

With function

def my_function(value, param1=undefined, param2=undefined):
    if param1 is undefined:
        # we know nothing was passed to it, not even None
        log_something('param1 was missing')
        param1 = None


    if param2 is undefined:
        # we got nothing here either
        log_something('param2 was missing')
        param2 = None

With dict

value = some_dict.get('some_key', undefined)
if value is None:
    log_something("'some_key' was set to None")

if value is undefined:
    # we know that the dict didn't have 'some_key'
    log_something("'some_key' was not set at all")
    value = None

With an object

value = getattr(obj, 'some_attribute', undefined) 
if value is None:
    log_something("'obj.some_attribute' was set to None")
if value is undefined:
    # we know that there's no obj.some_attribute
    log_something("no 'some_attribute' set on obj")
    value = None

As I mentioned earlier custom sentinels come with some caveats. First, they’re not keywords like None, so python doesn’t protect them. You can overwrite your undefined above at any time, anywhere in the module it’s defined, so be careful how you expose and use them. Next, the instance returned by object() is not a singleton, if you make that call 10 times you get 10 different objects. Finally, usage of a sentinel is highly idiosyncratic. A sentinel is specific to the library it’s used in and as such its scope should generally be limited to the library’s internals. It shouldn’t “leak” out. External code should only become aware of it, if their purpose is to extend or supplement the library’s API.


回答 2

它不像其他语言那样称为null,而是None。此对象始终只有一个实例,因此您可以根据需要使用x is None(同一性比较)而不是来检查是否相等x == None

It’s not called null as in other languages, but None. There is always only one instance of this object, so you can check for equivalence with x is None (identity comparison) instead of x == None, if you want.


回答 3

在Python中,要表示缺少值,可以对对象使用None值(types.NoneType.None),对字符串使用“”(或len()== 0)。因此:

if yourObject is None:  # if yourObject == None:
    ...

if yourString == "":  # if yourString.len() == 0:
    ...

关于“ ==”和“ is”之间的区别,使用“ ==”测试对象身份就足够了。但是,由于将“ is”操作定义为对象标识操作,因此使用它而不是“ ==”可能更正确。不知道是否存在速度差异。

无论如何,您可以看一下:

In Python, to represent the absence of a value, you can use the None value (types.NoneType.None) for objects and “” (or len() == 0) for strings. Therefore:

if yourObject is None:  # if yourObject == None:
    ...

if yourString == "":  # if yourString.len() == 0:
    ...

Regarding the difference between “==” and “is”, testing for object identity using “==” should be sufficient. However, since the operation “is” is defined as the object identity operation, it is probably more correct to use it, rather than “==”. Not sure if there is even a speed difference.

Anyway, you can have a look at:


回答 4

Null是一种特殊的对象类型,例如:

>>>type(None)
<class 'NoneType'>

您可以检查对象是否在类“ NoneType”中:

>>>variable = None
>>>variable is None
True

有关更多信息,请参见Python Docs。

Null is a special object type like:

>>>type(None)
<class 'NoneType'>

You can check if an object is in class ‘NoneType’:

>>>variable = None
>>>variable is None
True

More information is available at Python Docs


回答 5

Per Truth值测试,“ None”直接测试为FALSE,因此最简单的表达式就足够了:

if not foo:

Per Truth value testing, ‘None’ directly tests as FALSE, so the simplest expression will suffice:

if not foo:

致命错误:Python.h:没有这样的文件或目录

问题:致命错误:Python.h:没有这样的文件或目录

我正在尝试使用C扩展文件构建共享库,但首先我必须使用以下命令生成输出文件:

gcc -Wall utilsmodule.c -o Utilc

执行命令后,我得到以下错误消息:

utilsmodule.c:1:20:致命错误:Python.h:没有此类文件或目录编译终止。

我已经尝试了所有建议的解决方案,但是仍然存在该问题。我没有问题Python.h。我设法在机器上找到该文件。

I am trying to build a shared library using a C extension file but first I have to generate the output file using the command below:

gcc -Wall utilsmodule.c -o Utilc

After executing the command, I get this error message:

utilsmodule.c:1:20: fatal error: Python.h: No such file or directory compilation terminated.

I have tried all the suggested solutions over the internet but the problem still exists. I have no problem with Python.h. I managed to locate the file on my machine.


回答 0

看来您尚未正确安装python dev的标头文件和静态库。使用软件包管理器在系统范围内安装它们。

对于aptUbuntu,Debian …):

sudo apt-get install python-dev   # for python2.x installs
sudo apt-get install python3-dev  # for python3.x installs

对于yumCentOS,RHEL …):

sudo yum install python-devel   # for python2.x installs
sudo yum install python3-devel   # for python3.x installs

对于dnfFedora …):

sudo dnf install python2-devel  # for python2.x installs
sudo dnf install python3-devel  # for python3.x installs

对于zypperopenSUSE …):

sudo zypper in python-devel   # for python2.x installs
sudo zypper in python3-devel  # for python3.x installs

对于apkAlpine …):

# This is a departure from the normal Alpine naming
# scheme, which uses py2- and py3- prefixes
sudo apk add python2-dev  # for python2.x installs
sudo apk add python3-dev  # for python3.x installs

对于apt-cygCygwin …):

apt-cyg install python-devel   # for python2.x installs
apt-cyg install python3-devel  # for python3.x installs

Looks like you haven’t properly installed the header files and static libraries for python dev. Use your package manager to install them system-wide.

For apt (Ubuntu, Debian…):

sudo apt-get install python-dev   # for python2.x installs
sudo apt-get install python3-dev  # for python3.x installs

For yum (CentOS, RHEL…):

sudo yum install python-devel   # for python2.x installs
sudo yum install python3-devel   # for python3.x installs

For dnf (Fedora…):

sudo dnf install python2-devel  # for python2.x installs
sudo dnf install python3-devel  # for python3.x installs

For zypper (openSUSE…):

sudo zypper in python-devel   # for python2.x installs
sudo zypper in python3-devel  # for python3.x installs

For apk (Alpine…):

# This is a departure from the normal Alpine naming
# scheme, which uses py2- and py3- prefixes
sudo apk add python2-dev  # for python2.x installs
sudo apk add python3-dev  # for python3.x installs

For apt-cyg (Cygwin…):

apt-cyg install python-devel   # for python2.x installs
apt-cyg install python3-devel  # for python3.x installs

回答 1

在Ubuntu上,我正在运行Python 3,必须安装

sudo apt-get install python3-dev

如果要使用未链接到python3的Python版本,请安装关联的python3.x-dev软件包。例如:

sudo apt-get install python3.5-dev

On Ubuntu, I was running Python 3 and I had to install

sudo apt-get install python3-dev

If you want to use a version of Python that is not linked to python3, install the associated python3.x-dev package. For example:

sudo apt-get install python3.5-dev

回答 2

特别是对于Python 3.7Ubuntu,我需要

sudo apt install libpython3.7-dev

。我认为在某些时候名称已从此更改pythonm.n-dev

对于Python 3.6,类似地:

sudo apt install libpython3.6-dev

For Python 3.7 and Ubuntu in particular, I needed

sudo apt install libpython3.7-dev

. I think at some point names were changed from pythonm.n-dev to this.


回答 3

您必须做两件事。

为Debian / Ubuntu / Mint安装适用于Python的开发包,可通过以下命令完成:

sudo apt-get install python-dev

第二件事是,默认情况下,包含文件不在包含路径中,Python库也不与可执行文件链接。您需要添加这些标志(相应地替换Python的版本):

-I/usr/include/python2.7 -lpython2.7 

换句话说,您的编译命令应为:

gcc -Wall -I/usr/include/python2.7 -lpython2.7  utilsmodule.c -o Utilc 

Two things you have to do.

Install development package for Python, in case of Debian/Ubuntu/Mint it’s done with command:

sudo apt-get install python-dev

Second thing is that include files are not by default in the include path, nor is Python library linked with executable by default. You need to add these flags (replace Python’s version accordingly):

-I/usr/include/python2.7 -lpython2.7 

In other words your compile command ought to be:

gcc -Wall -I/usr/include/python2.7 -lpython2.7  utilsmodule.c -o Utilc 

回答 4

如果您使用的是Raspberry Pi:

sudo apt-get install python-dev

If you are using a Raspberry Pi:

sudo apt-get install python-dev

回答 5

在Fedora上针对Python 2运行它:

sudo dnf install python2-devel

而对于Python 3:

sudo dnf install python3-devel

on Fedora run this for Python 2:

sudo dnf install python2-devel

and for Python 3:

sudo dnf install python3-devel

回答 6

如果要使用tox在多个版本的Python上运行测试,则可能需要为要测试的每个Python版本安装Python开发库。

sudo apt-get install python2.6-dev 
sudo apt-get install python2.7-dev 
etc.

If you are using tox to run tests on multiple versions of Python, you may need to install the Python dev libraries for each version of Python you are testing on.

sudo apt-get install python2.6-dev 
sudo apt-get install python2.7-dev 
etc.

回答 7

Cygwin的解决方案

您需要安装软件包python2-develpython3-devel,具体取决于您使用的Python版本。

您可以使用Cygwin.com上的32位64位 setup.exe(取决于您的安装)快速安装它。

示例(setup.exe如果需要,可以修改的文件名和Python的主要版本):

$ setup.exe -q --packages=python3-devel

您也可以在其他答案中查看我的其他答案,以从命令行安装Cygwin的软件包。

Solution for Cygwin

You need to install the package python2-devel or python3-devel, depending on the Python version you’re using.

You can quickly install it using the 32-bit or 64-bit setup.exe (depending on your installation) from Cygwin.com.

Example (modify setup.exe‘s filename and Python’s major version if you need):

$ setup.exe -q --packages=python3-devel

You can also check my other answer for a few more options to install Cygwin’s packages from the command-line.


回答 8

在AWS API(centOS)中

yum install python27-devel

In AWS API (centOS) its

yum install python27-devel

回答 9

对我来说,将其更改为有效:

#include <python2.7/Python.h>

我找到了文件/usr/include/python2.7/Python.h,并且由于/usr/include已经在include路径中,因此python2.7/Python.h应该足够了。

您也可以从命令行添加包含路径- gcc -I/usr/lib/python2.7(感谢@ erm3nda)。

For me, changing it to this worked:

#include <python2.7/Python.h>

I found the file /usr/include/python2.7/Python.h, and since /usr/include is already in the include path, then python2.7/Python.h should be sufficient.

You could also add the include path from command line instead – gcc -I/usr/lib/python2.7 (thanks @erm3nda).


回答 10

确保您的操作系统随附Python开发文件。

您不应该对库进行硬编码并包含路径。而是使用pkg-config,它将为您的特定系统输出正确的选项:

$ pkg-config --cflags --libs python2 -I/usr/include/python2.7 -lpython2.7

您可以将其添加到您的gcc行:

gcc -Wall utilsmodule.c -o Utilc $(pkg-config --cflags --libs python2) 

Make sure that the Python dev files come with your OS.

You should not hard code the library and include paths. Instead, use pkg-config, which will output the correct options for your specific system:

$ pkg-config --cflags --libs python2 -I/usr/include/python2.7 -lpython2.7

You may add it to your gcc line:

gcc -Wall utilsmodule.c -o Utilc $(pkg-config --cflags --libs python2) 

回答 11

运行python34的AWS EC2安装:

sudo yum install python34-devel

AWS EC2 install running python34:

sudo yum install python34-devel


回答 12

就我而言,在Ubuntu中修复该问题的是安装软件包libpython-all-dev(或者libpython3-all-dev如果您使用Python 3)。

In my case, what fixed it in Ubuntu was to install the packages libpython-all-dev (or libpython3-all-dev if you use Python 3).


回答 13

如果您使用带有3.6 python的virtualenv(现在是edge),请确保安装匹配的python 3.6 dev sudo apt-get install python3.6-dev,否则执行sudo python3-dev将安装python dev 3.3.3-1,这将无法解决问题。

If you use a virtualenv with a 3.6 python (edge right now), be sure to install the matching python 3.6 dev sudo apt-get install python3.6-dev, otherwise executing sudo python3-dev will install the python dev 3.3.3-1, which won’t solve the issue.


回答 14

情况不一样,但对我也适用,现在我可以在Python3.5中使用SWIG了:

我正在尝试编译:

gcc -fPIC -c existe.c existe_wrap.c -I /usr/include/python3.5m/

使用Python 2.7可以正常工作,而不能用于我的3.5版本:

existe_wrap.c:147:21:致命错误:Python.h:没有存档或目录编译终止。

在我的Ubuntu 16.04安装中运行后:

sudo apt-get install python3-dev  # for python3.x installs

现在,我可以毫无问题地编译Python3.5了:

gcc -fPIC -c existe.c existe_wrap.c -I /usr/include/python3.5m/

It’s not the same situation, but it also works for me and now I can use SWIG with Python3.5:

I was trying to compile:

gcc -fPIC -c existe.c existe_wrap.c -I /usr/include/python3.5m/

With Python 2.7 works fine, not with my version 3.5:

existe_wrap.c:147:21: fatal error: Python.h: No existe el archivo o el directorio compilation terminated.

After run in my Ubuntu 16.04 installation:

sudo apt-get install python3-dev  # for python3.x installs

Now I can compile without problems Python3.5:

gcc -fPIC -c existe.c existe_wrap.c -I /usr/include/python3.5m/

回答 15

我在ubuntu中安装coolprop时也遇到了此错误。

对于带有python 3.6的ubuntu 16.04

sudo apt-get install python3.6-dev

如果这不起作用,请尝试安装/更新gcclib。

sudo apt-get install gcc

I also encountered this error when I was installing coolprop in ubuntu.

For ubuntu 16.04 with python 3.6

sudo apt-get install python3.6-dev

If ever this doesn’t work try installing/updating gcc lib.

sudo apt-get install gcc

回答 16

尝试apt文件。很难记住丢失文件所在的软件包名称。它是通用的,对任何软件包文件都有用。

例如:

root@ubuntu234:~/auto# apt-file search --regexp '/Python.h$'
pypy-dev: /usr/lib/pypy/include/Python.h
python2.7-dbg: /usr/include/python2.7_d/Python.h
python2.7-dev: /usr/include/python2.7/Python.h
python3.2-dbg: /usr/include/python3.2dmu/Python.h
python3.2-dev: /usr/include/python3.2mu/Python.h
root@ubuntu234:~/auto# 

现在,您可以对要选择的专家进行猜测。

try apt-file. It is difficult to remember the package name where the missing file resides. It is generic and useful for any package files.

For example:

root@ubuntu234:~/auto# apt-file search --regexp '/Python.h$'
pypy-dev: /usr/lib/pypy/include/Python.h
python2.7-dbg: /usr/include/python2.7_d/Python.h
python2.7-dev: /usr/include/python2.7/Python.h
python3.2-dbg: /usr/include/python3.2dmu/Python.h
python3.2-dev: /usr/include/python3.2mu/Python.h
root@ubuntu234:~/auto# 

Now you can make an expert guess as to which one to choose from.


回答 17

我设法解决了这个问题,并在一个命令中生成了.so文件

gcc -shared -o UtilcS.so
-fPIC -I/usr/include/python2.7 -lpython2.7  utilsmodule.c

I managed to solve this issue and generate the .so file in one command

gcc -shared -o UtilcS.so
-fPIC -I/usr/include/python2.7 -lpython2.7  utilsmodule.c

回答 18

对于OpenSuse同志:

sudo zypper install python3-devel

For the OpenSuse comrades out there:

sudo zypper install python3-devel

回答 19

对于CentOS 7:

sudo yum install python36u-devel

我按照此处的说明在多个VM上安装python3.6:https ://www.digitalocean.com/community/tutorials/how-to-install-python-3-and-set-up-a-local-programming- 在centos-7上运行 ,然后能够构建mod_wsgi并使其与python3.6 virtualenv一起使用

For CentOS 7:

sudo yum install python36u-devel

I followed the instructions here for installing python3.6 on several VMs: https://www.digitalocean.com/community/tutorials/how-to-install-python-3-and-set-up-a-local-programming-environment-on-centos-7 and was then able to build mod_wsgi and get it working with a python3.6 virtualenv


回答 20

如果您在Amazon Linux上使用Python 3.6(基于RHEL,但此处给出的RHEL答案无效):

sudo yum install python36-devel

If you’re using Python 3.6 on Amazon Linux (based on RHEL, but the RHEL answers given here didn’t work):

sudo yum install python36-devel

回答 21

当我尝试使用Python3.6在CentOS 7上安装ctds时发生此错误。我做了这里提到的所有技巧,包括yum install python34-devel。在Python.h中发现了问题/usr/include/python3.4m but not in /usr/include/python3.6m。我试图--global-option指向包含dir(pip3.6 install --global-option=build_ext --global-option="--include-dirs=/usr/include/python3.4m" ctds)的位置。导致在lpython3.6m链接ctds时找不到。

最后,有效的方法是修复Python3.6的开发环境,需要使用include和libs进行更正。

yum -y install https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/python36u-libs-3.6.3-1.ius.centos7.x86_64.rpm

Python.h必须位于gcc的包含路径中。无论使用哪个版本的python(例如,如果版本为3.6,则/usr/include/python3.6m/Python.h通常都应使用该版本)。

This error occurred when I attempted to install ctds on CentOS 7 with Python3.6. I did all the tricks mentioned here including yum install python34-devel. The problem was Python.h was found in /usr/include/python3.4m but not in /usr/include/python3.6m. I tried to use --global-option to point to include dir (pip3.6 install --global-option=build_ext --global-option="--include-dirs=/usr/include/python3.4m" ctds). This resulted in a lpython3.6m not found when linking ctds.

Finally what worked was fixing the development environment for Python3.6 needs to correct with the include and libs.

yum -y install https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/python36u-libs-3.6.3-1.ius.centos7.x86_64.rpm

Python.h needs to be in your include path for gcc. Whichever version of python is used, for example if it’s 3.6, then it should be in /usr/include/python3.6m/Python.h typically.


回答 22

当然,python-dev还是libpython-all-devapt)的第一件事install,但是,如果这对我的情况没有帮助,我建议您通过和安装外部功能接口软件包。sudo apt-get install libffi-devsudo pip install cffi

如果您看到错误信息as / from,这应该会有所帮助c/_cffi_backend.c:2:20: fatal error: Python.h: No such file or directory

Sure python-dev or libpython-all-dev are the first thing to (apt )install, but if that doesn’t help as was my case, I advice you to install the foreign Function Interface packages by sudo apt-get install libffi-dev and sudo pip install cffi.

This should help out especially if you see the error as/from c/_cffi_backend.c:2:20: fatal error: Python.h: No such file or directory.


回答 23

当您尝试删除python3.5和安装时,它经常出现python3.6

因此,当使用python3(which python3 -V=> python3.6)安装某些软件包时,所需的python3.5标头将出现此错误。

通过安装python3.6-dev模块解决。

It often appear when you trying to remove python3.5 and install python3.6.

So when using python3 (which python3 -V => python3.6) to install some packages required python3.5 header will appear this error.

Resolve by install python3.6-dev module.


回答 24

  1. 如果操作系统随附的Python不附带Python开发文件,则必须在其上安装Python开发文件。关于这个问题的许多答案显示了在不同系统上可以实现的无数种方法。

  2. 您这样做时,问题是告诉编译器它们的位置以及如何针对它们进行编译。Python附带了一个名为的程序python-config。对于编译,您需要--includes输出,并且需要将程序链接到Python库(将Python嵌入程序中)到--ldflags输出。例:

    gcc -c mypythonprogram.c $(python3-config --includes)
    gcc -o program mypythonprogram.o $(python3-config --ldflags)

python-config程序可以以Python版本命名-例如在Debian,Ubuntu上,它们可以命名为python3-configpython3.6-config

  1. You must install the Python development files on your operating system if the Python provided with your operating system does not come with them. The many answers on this question show the myriad ways this can be achieved on different systems.

  2. When you have done so, the problem is telling the compiler where they’re located and how to compile against them. Python comes with a program called python-config. For compilation, you need the --includes output and for linking a program against the Python library (embedding Python into your program) the --ldflags output. Example:

    gcc -c mypythonprogram.c $(python3-config --includes)
    gcc -o program mypythonprogram.o $(python3-config --ldflags)
    

The python-config program can be named after the Python versions – on Debian, Ubuntu for example these can be named python3-config or python3.6-config.


回答 25

有时即使安装了python-dev之后,错误仍然存​​在,如果没有’gcc’,请检查错误。

首先按照https://stackoverflow.com/a/21530768/8687063中的说明进行下载,然后安装gcc

对于apt(Ubuntu,Debian …):

sudo apt-get install gcc

对于百胜(CentOS,RHEL …):

sudo yum install gcc

对于dnf(Fedora …):

sudo dnf install gcc

对于zypper(openSUSE …):

sudo zypper in gcc

对于apk(高山…):

sudo apk gcc

Sometimes even after installing python-dev the error persists, Check for the error if it is ‘gcc’ missing.

First download as stated in https://stackoverflow.com/a/21530768/8687063, then install gcc

For apt (Ubuntu, Debian…):

sudo apt-get install gcc

For yum (CentOS, RHEL…):

sudo yum install gcc

For dnf (Fedora…):

sudo dnf install gcc

For zypper (openSUSE…):

sudo zypper in gcc

For apk (Alpine…):

sudo apk gcc

回答 26

这意味着它Python.h不在编译器的默认包含路径中。您在系统范围内还是在本地安装了它?您的操作系统是什么?

您可以使用该-I<path>标志指定编译器应在其中查找标头的其他目录。您可能需要跟进,-L<path>以便gcc可以找到要使用链接的库-l<name>

This means that Python.h isn’t in your compiler’s default include paths. Have you installed it system-wide or locally? What’s your OS?

You could use the -I<path> flag to specify an additional directory where your compiler should look for headers. You will probably have to follow up with -L<path> so that gcc can find the library you’ll be linking with using -l<name>.


如何检查正在运行脚本的Python版本?

问题:如何检查正在运行脚本的Python版本?

如何检查正在解释脚本的版本的Python Interpreter?

How can I check what version of the Python Interpreter is interpreting my script?


回答 0

sys模块的sys.version字符串中提供了此信息:

>>> import sys

可读性:

>>> print(sys.version)  # parentheses necessary in python 3.       
2.5.2 (r252:60911, Jul 31 2008, 17:28:52) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]

进行进一步处理:

>>> sys.version_info
(2, 5, 2, 'final', 0)
# or
>>> sys.hexversion
34014192

为确保脚本以Python解释器的最低版本要求运行,请将其添加到您的代码中:

assert sys.version_info >= (2, 5)

这将比较主要版本和次要版本信息。微(=添加01等等),甚至releaselevel(= 'alpha''final'等)的元组只要你喜欢。但是请注意,最好总是“躲开”检查是否存在某个功能,如果不存在,则要变通(或纾困)。有时,某些功能在较新的版本中会消失,而被其他功能取代。

This information is available in the sys.version string in the sys module:

>>> import sys

Human readable:

>>> print(sys.version)  # parentheses necessary in python 3.       
2.5.2 (r252:60911, Jul 31 2008, 17:28:52) 
[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)]

For further processing:

>>> sys.version_info
(2, 5, 2, 'final', 0)
# or
>>> sys.hexversion
34014192

To ensure a script runs with a minimal version requirement of the Python interpreter add this to your code:

assert sys.version_info >= (2, 5)

This compares major and minor version information. Add micro (=0, 1, etc) and even releaselevel (='alpha','final', etc) to the tuple as you like. Note however, that it is almost always better to “duck” check if a certain feature is there, and if not, workaround (or bail out). Sometimes features go away in newer releases, being replaced by others.


回答 1

在命令行中(注意大写的“ V”):

python -V

在’man python’中有记录。

From the command line (note the capital ‘V’):

python -V

This is documented in ‘man python’.


回答 2

我喜欢这样sys.hexversion的东西。

http://docs.python.org/library/sys.html#sys.hexversion

>>> import sys
>>> sys.hexversion
33883376
>>> '%x' % sys.hexversion
'20504f0'
>>> sys.hexversion < 0x02060000
True

I like sys.hexversion for stuff like this.

http://docs.python.org/library/sys.html#sys.hexversion

>>> import sys
>>> sys.hexversion
33883376
>>> '%x' % sys.hexversion
'20504f0'
>>> sys.hexversion < 0x02060000
True

回答 3

您最好的选择可能是这样的:

>>> import sys
>>> sys.version_info
(2, 6, 4, 'final', 0)
>>> if not sys.version_info[:2] == (2, 6):
...    print "Error, I need python 2.6"
... else:
...    from my_module import twoPointSixCode
>>> 

此外,您始终可以通过简单的尝试将导入文件包装起来,这样可以捕获语法错误。而且,就@Heikki而言,此代码将与许多旧版本的python兼容:

>>> try:
...     from my_module import twoPointSixCode
... except Exception: 
...     print "can't import, probably because your python is too old!"
>>>

Your best bet is probably something like so:

>>> import sys
>>> sys.version_info
(2, 6, 4, 'final', 0)
>>> if not sys.version_info[:2] == (2, 6):
...    print "Error, I need python 2.6"
... else:
...    from my_module import twoPointSixCode
>>> 

Additionally, you can always wrap your imports in a simple try, which should catch syntax errors. And, to @Heikki’s point, this code will be compatible with much older versions of python:

>>> try:
...     from my_module import twoPointSixCode
... except Exception: 
...     print "can't import, probably because your python is too old!"
>>>

回答 4

使用platformpython_version从STDLIB:

>>> from platform import python_version
>>> print(python_version())
2.7.8

Use platform‘s python_version from the stdlib:

>>> from platform import python_version
>>> print(python_version())
2.7.8

回答 5

放入类似:

#!/usr/bin/env/python
import sys
if sys.version_info<(2,6,0):
  sys.stderr.write("You need python 2.6 or later to run this script\n")
  exit(1)

在脚本的顶部。

请注意,取决于脚本中的内容,比目标版本更旧的python甚至可能无法加载脚本,因此无法报告该错误。解决方法是,您可以在脚本中运行以上命令,该脚本将使用更现代的代码导入该脚本。

Put something like:

#!/usr/bin/env/python
import sys
if sys.version_info<(2,6,0):
  sys.stderr.write("You need python 2.6 or later to run this script\n")
  exit(1)

at the top of your script.

Note that depending on what else is in your script, older versions of python than the target may not be able to even load the script, so won’t get far enough to report this error. As a workaround, you can run the above in a script that imports the script with the more modern code.


回答 6

这是一个简短的命令行版本,可以立即退出(对于脚本和自动执行非常方便):

python -c "print(__import__('sys').version)"

或者只是主要,次要和微观:

python -c "print(__import__('sys').version_info[:1])" # (2,)
python -c "print(__import__('sys').version_info[:2])" # (2, 7)
python -c "print(__import__('sys').version_info[:3])" # (2, 7, 6)

Here’s a short commandline version which exits straight away (handy for scripts and automated execution):

python -c "print(__import__('sys').version)"

Or just the major, minor and micro:

python -c "print(__import__('sys').version_info[:1])" # (2,)
python -c "print(__import__('sys').version_info[:2])" # (2, 7)
python -c "print(__import__('sys').version_info[:3])" # (2, 7, 6)

回答 7

使用six模块,您可以通过以下方法实现:

import six

if six.PY2:
  # this is python2.x
else:
  # six.PY3
  # this is python3.x

With six module, you can do it by:

import six

if six.PY2:
  # this is python2.x
else:
  # six.PY3
  # this is python3.x

回答 8

import sys
sys.version.split(' ')[0]

sys.version提供您想要的,只需选择第一个数字即可:)

import sys
sys.version.split(' ')[0]

sys.version gives you what you want, just pick the first number :)


回答 9

最简单的方法

只需在终端中键入python,您就可以看到如下所示的版本

desktop:~$ python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

The simplest way

Just type python in your terminal and you can see the version as like following

desktop:~$ python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

回答 10

就像Seth所说的那样,主脚本可以检查sys.version_info(但是请注意,直到2.0才出现),因此,如果要支持旧版本,则需要检查sys模块的另一个版本属性。

但是,您仍然需要注意不要使用该文件中的任何Python语言功能,这些功能在较早的Python版本中不可用。例如,在Python 2.5和更高版本中允许这样做:

try:
    pass
except:
    pass
finally:
    pass

但在较旧的Python版本中将无法使用,因为您只能使用OR或最终与try匹配。因此,为了与旧版本的Python兼容,您需要编写:

try:
    try:
        pass
    except:
        pass
finally:
    pass

Like Seth said, the main script could check sys.version_info (but note that that didn’t appear until 2.0, so if you want to support older versions you would need to check another version property of the sys module).

But you still need to take care of not using any Python language features in the file that are not available in older Python versions. For example, this is allowed in Python 2.5 and later:

try:
    pass
except:
    pass
finally:
    pass

but won’t work in older Python versions, because you could only have except OR finally match the try. So for compatibility with older Python versions you need to write:

try:
    try:
        pass
    except:
        pass
finally:
    pass

回答 11

一些答案已经建议如何查询当前的python版本。为了以编程方式检查版本要求,我将使用以下两种方法之一:

# Method 1: (see krawyoti's answer)
import sys
assert(sys.version_info >= (2,6))

# Method 2: 
import platform
from distutils.version import StrictVersion 
assert(StrictVersion(platform.python_version()) >= "2.6")

Several answers already suggest how to query the current python version. To check programmatically the version requirements, I’d make use of one of the following two methods:

# Method 1: (see krawyoti's answer)
import sys
assert(sys.version_info >= (2,6))

# Method 2: 
import platform
from distutils.version import StrictVersion 
assert(StrictVersion(platform.python_version()) >= "2.6")

回答 12

只是为了好玩,下面是在CPython 1.0-3.7b2,Pypy,Jython和Micropython上执行此操作的一种方法。这更多是出于好奇,而不是现代代码中的一种实现方式。我将其作为http://stromberg.dnsalias.org/~strombrg/pythons/的一部分编写的,该脚本是用于一次在多个python版本上测试代码段的脚本,因此您可以轻松了解python的种类功能与python版本兼容:

via_platform = 0
check_sys = 0
via_sys_version_info = 0
via_sys_version = 0
test_sys = 0
try:
    import platform
except (ImportError, NameError):
    # We have no platform module - try to get the info via the sys module
    check_sys = 1

if not check_sys:
    if hasattr(platform, "python_version"):
        via_platform = 1
    else:
        check_sys = 1

if check_sys:
    try:
        import sys
        test_sys = 1
    except (ImportError, NameError):
        # just let via_sys_version_info and via_sys_version remain False - we have no sys module
        pass

if test_sys:
    if hasattr(sys, "version_info"):
        via_sys_version_info = 1
    elif hasattr(sys, "version"):
        via_sys_version = 1
    else:
        # just let via_sys remain False
        pass

if via_platform:
    # This gives pretty good info, but is not available in older interpreters.  Also, micropython has a
    # platform module that does not really contain anything.
    print(platform.python_version())
elif via_sys_version_info:
    # This is compatible with some older interpreters, but does not give quite as much info.
    print("%s.%s.%s" % sys.version_info[:3])
elif via_sys_version:
    import string
    # This is compatible with some older interpreters, but does not give quite as much info.
    verbose_version = sys.version
    version_list = string.split(verbose_version)
    print(version_list[0])
else:
    print("unknown")

Just for fun, the following is a way of doing it on CPython 1.0-3.7b2, Pypy, Jython and Micropython. This is more of a curiosity than a way of doing it in modern code. I wrote it as part of http://stromberg.dnsalias.org/~strombrg/pythons/ , which is a script for testing a snippet of code on many versions of python at once, so you can easily get a feel for what python features are compatible with what versions of python:

via_platform = 0
check_sys = 0
via_sys_version_info = 0
via_sys_version = 0
test_sys = 0
try:
    import platform
except (ImportError, NameError):
    # We have no platform module - try to get the info via the sys module
    check_sys = 1

if not check_sys:
    if hasattr(platform, "python_version"):
        via_platform = 1
    else:
        check_sys = 1

if check_sys:
    try:
        import sys
        test_sys = 1
    except (ImportError, NameError):
        # just let via_sys_version_info and via_sys_version remain False - we have no sys module
        pass

if test_sys:
    if hasattr(sys, "version_info"):
        via_sys_version_info = 1
    elif hasattr(sys, "version"):
        via_sys_version = 1
    else:
        # just let via_sys remain False
        pass

if via_platform:
    # This gives pretty good info, but is not available in older interpreters.  Also, micropython has a
    # platform module that does not really contain anything.
    print(platform.python_version())
elif via_sys_version_info:
    # This is compatible with some older interpreters, but does not give quite as much info.
    print("%s.%s.%s" % sys.version_info[:3])
elif via_sys_version:
    import string
    # This is compatible with some older interpreters, but does not give quite as much info.
    verbose_version = sys.version
    version_list = string.split(verbose_version)
    print(version_list[0])
else:
    print("unknown")

回答 13

检查Python版本:python -Vpython --versionapt-cache policy python

您还可以运行whereis python以查看安装了多少个版本。

Check Python version: python -V or python --version or apt-cache policy python

you can also run whereis python to see how many versions are installed.


回答 14

如果您想检测Python 3之前的版本并且不想导入任何东西…

…您可以(ab)使用列表理解范围的更改,并在单个表达式中完成

is_python_3_or_above = (lambda x: [x for x in [False]] and None or x)(True)

If you want to detect pre-Python 3 and don’t want to import anything…

…you can (ab)use list comprehension scoping changes and do it in a single expression:

is_python_3_or_above = (lambda x: [x for x in [False]] and None or x)(True)

回答 15

要在Windows上验证Python版本的命令,请在命令提示符下运行以下命令并验证输出

c:\>python -V
Python 2.7.16

c:\>py -2 -V
Python 2.7.16

c:\>py -3 -V
Python 3.7.3

另外,要查看每个Python版本的文件夹配置,请运行以下命令:

For Python 2,'py -2 -m site'
For Python 3,'py -3 -m site'

To verify the Python version for commands on Windows, run the following commands in a command prompt and verify the output

c:\>python -V
Python 2.7.16

c:\>py -2 -V
Python 2.7.16

c:\>py -3 -V
Python 3.7.3

Also, To see the folder configuration for each Python version, run the following commands:

For Python 2,'py -2 -m site'
For Python 3,'py -3 -m site'

回答 16

from sys import version_info, api_version, version, hexversion

print(f"sys.version: {version}")
print(f"sys.api_version: {api_version}")
print(f"sys.version_info: {version_info}")
print(f"sys.hexversion: {hexversion}")

输出

sys.version: 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)]
sys.api_version: 1013
sys.version_info: sys.version_info(major=3, minor=6, micro=5, releaselevel='final', serial=0)
sys.hexversion: 50726384
from sys import version_info, api_version, version, hexversion

print(f"sys.version: {version}")
print(f"sys.api_version: {api_version}")
print(f"sys.version_info: {version_info}")
print(f"sys.hexversion: {hexversion}")

output

sys.version: 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)]
sys.api_version: 1013
sys.version_info: sys.version_info(major=3, minor=6, micro=5, releaselevel='final', serial=0)
sys.hexversion: 50726384

回答 17

sys.version_infotuple从3.7开始似乎没有返回a 。相反,它返回一个特殊的类,因此至少对于我来说,所有使用元组的示例都不起作用。这是python控制台的输出:

>>> import sys
>>> type(sys.version_info)
<class 'sys.version_info'>

我发现结合使用sys.version_info.majorsys.version_info.minor似乎足够了。例如,…

import sys
if sys.version_info.major > 3:
    print('Upgrade to Python 3')
    exit(1)

检查您是否正在运行Python3。您甚至可以使用…检查更特定的版本。

import sys
ver = sys.version_info
if ver.major > 2:
    if ver.major == 3 and ver.minor <= 4:
        print('Upgrade to Python 3.5')
        exit(1)

可以检查您是否至少运行Python 3.5。

sys.version_info doesn’t seem to return a tuple as of 3.7. Rather, it returns a special class, so all of the examples using tuples don’t work, for me at least. Here’s the output from a python console:

>>> import sys
>>> type(sys.version_info)
<class 'sys.version_info'>

I’ve found that using a combination of sys.version_info.major and sys.version_info.minor seems to suffice. For example,…

import sys
if sys.version_info.major > 3:
    print('Upgrade to Python 3')
    exit(1)

checks if you’re running Python 3. You can even check for more specific versions with…

import sys
ver = sys.version_info
if ver.major > 2:
    if ver.major == 3 and ver.minor <= 4:
        print('Upgrade to Python 3.5')
        exit(1)

can check to see if you’re running at least Python 3.5.


回答 18

最简单的方法:

在Spyder中,启动新的“ IPython Console”,然后运行任何现有脚本。

现在,可以在控制台窗口中打印的第一个输出中看到版本:

“ Python 3.7.3(默认值,2019年4月24日,15:29:51)…”

在此处输入图片说明

The even simpler simplest way:

In Spyder, start a new “IPython Console”, then run any of your existing scripts.

Now the version can be seen in the first output printed in the console window:

“Python 3.7.3 (default, Apr 24 2019, 15:29:51)…”

enter image description here


回答 19

要从命令行检查,只需一个命令,但要包含主要,次要,微型版本,发行版和序列号

> python -c "import sys; print('{}.{}.{}-{}-{}'.format(*sys.version_info))"

3.7.6-final-0

注意:.format()代替f字符串,或者'.'.join()允许您使用任意格式和分隔符char,例如,使其成为可抓握的单字字符串。我将其放在报告所有重要版本的bash实用程序脚本中:python,numpy,pandas,sklearn,MacOS,xcode,clang,brew,conda,anaconda,gcc / g ++等。对于日志记录,可复制性,故障排除报告等很有用。

To check from the command-line, in one single command, but include major, minor, micro version, releaselevel and serial:

> python -c "import sys; print('{}.{}.{}-{}-{}'.format(*sys.version_info))"

3.7.6-final-0

Note: .format() instead of f-strings or '.'.join() allows you to use arbitrary formatting and separator chars, e.g. to make this a greppable one-word string. I put this inside a bash utility script that reports all important versions: python, numpy, pandas, sklearn, MacOS, xcode, clang, brew, conda, anaconda, gcc/g++ etc. Useful for logging, replicability, troubleshootingm bug-reporting etc.


回答 20

如果您在linux上工作,请给出命令python 输出将如下所示

Python 2.4.3(#1,2009年6月11日,14:09:37)

linux2上的[GCC 4.1.2 20080704(Red Hat 4.1.2-44)]

键入“帮助”,“版权”,“信用”或“许可证”以获取更多信息。

If you are working on linux just give command python output will be like this

Python 2.4.3 (#1, Jun 11 2009, 14:09:37)

[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2

Type “help”, “copyright”, “credits” or “license” for more information.


如何使用Python连接到MySQL数据库?

问题:如何使用Python连接到MySQL数据库?

如何使用python程序连接到MySQL数据库?

How do I connect to a MySQL database using a python program?


回答 0

分三步使用Python 2连接到MYSQL

1-设定

在执行任何操作之前,必须安装MySQL驱动程序。与PHP不同,默认情况下,Python仅安装SQLite驱动程序。最常用的软件包是MySQLdb,但很难使用easy_install进行安装。请注意,MySQLdb仅支持Python 2。

对于Windows用户,您可以获取MySQLdbexe

对于Linux,这是一个临时包(python-mysqldb)。(您可以在命令行中使用sudo apt-get install python-mysqldb(对于基于debian的发行版),yum install MySQL-python(对于基于rpm的dnf install python-mysql发行版)或(对于现代的fedora发行版)进行下载。)

对于Mac,您可以使用Macport安装MySQLdb

2-用法

安装后,重新启动。这不是强制性的,但是如果出现问题,它将阻止我回答本文中的3个或4个其他问题。因此,请重新启动。

然后,就像使用其他任何软件包一样:

#!/usr/bin/python
import MySQLdb

db = MySQLdb.connect(host="localhost",    # your host, usually localhost
                     user="john",         # your username
                     passwd="megajonhy",  # your password
                     db="jonhydb")        # name of the data base

# you must create a Cursor object. It will let
#  you execute all the queries you need
cur = db.cursor()

# Use all the SQL you like
cur.execute("SELECT * FROM YOUR_TABLE_NAME")

# print all the first cell of all the rows
for row in cur.fetchall():
    print row[0]

db.close()

当然,有成千上万种可能性和选择。这是一个非常基本的例子。您将不得不查看文档。一个良好的起点

3-更高级的用法

了解了它的工作原理后,您可能希望使用ORM来避免手动编写SQL并像处理Python对象一样处理表。Python社区中最著名的ORM是SQLAlchemy

我强烈建议您使用它:您的生活将变得更加轻松。

我最近在Python世界中发现了另一种宝石:peewee。这是一个非常精简的ORM,非常易于安装和使用。对于小型项目或独立应用程序来说,这让我感到欣慰,而在使用SQLAlchemy或Django之类的大型工具的时候就显得过分了:

import peewee
from peewee import *

db = MySQLDatabase('jonhydb', user='john', passwd='megajonhy')

class Book(peewee.Model):
    author = peewee.CharField()
    title = peewee.TextField()

    class Meta:
        database = db

Book.create_table()
book = Book(author="me", title='Peewee is cool')
book.save()
for book in Book.filter(author="me"):
    print book.title

本示例开箱即用。除了带有peewee(pip install peewee)外,没有其他要求。

Connecting to MYSQL with Python 2 in three steps

1 – Setting

You must install a MySQL driver before doing anything. Unlike PHP, Only the SQLite driver is installed by default with Python. The most used package to do so is MySQLdb but it’s hard to install it using easy_install. Please note MySQLdb only supports Python 2.

For Windows user, you can get an exe of MySQLdb.

For Linux, this is a casual package (python-mysqldb). (You can use sudo apt-get install python-mysqldb (for debian based distros), yum install MySQL-python (for rpm-based), or dnf install python-mysql (for modern fedora distro) in command line to download.)

For Mac, you can install MySQLdb using Macport.

2 – Usage

After installing, Reboot. This is not mandatory, But it will prevent me from answering 3 or 4 other questions in this post if something goes wrong. So please reboot.

Then it is just like using any other package :

#!/usr/bin/python
import MySQLdb

db = MySQLdb.connect(host="localhost",    # your host, usually localhost
                     user="john",         # your username
                     passwd="megajonhy",  # your password
                     db="jonhydb")        # name of the data base

# you must create a Cursor object. It will let
#  you execute all the queries you need
cur = db.cursor()

# Use all the SQL you like
cur.execute("SELECT * FROM YOUR_TABLE_NAME")

# print all the first cell of all the rows
for row in cur.fetchall():
    print row[0]

db.close()

Of course, there are thousand of possibilities and options; this is a very basic example. You will have to look at the documentation. A good starting point.

3 – More advanced usage

Once you know how it works, You may want to use an ORM to avoid writing SQL manually and manipulate your tables as they were Python objects. The most famous ORM in the Python community is SQLAlchemy.

I strongly advise you to use it: your life is going to be much easier.

I recently discovered another jewel in the Python world: peewee. It’s a very lite ORM, really easy and fast to setup then use. It makes my day for small projects or stand alone apps, Where using big tools like SQLAlchemy or Django is overkill :

import peewee
from peewee import *

db = MySQLDatabase('jonhydb', user='john', passwd='megajonhy')

class Book(peewee.Model):
    author = peewee.CharField()
    title = peewee.TextField()

    class Meta:
        database = db

Book.create_table()
book = Book(author="me", title='Peewee is cool')
book.save()
for book in Book.filter(author="me"):
    print book.title

This example works out of the box. Nothing other than having peewee (pip install peewee) is required.


回答 1

这是使用MySQLdb的一种方法,该方法仅支持Python 2:

#!/usr/bin/python
import MySQLdb

# Connect
db = MySQLdb.connect(host="localhost",
                     user="appuser",
                     passwd="",
                     db="onco")

cursor = db.cursor()

# Execute SQL select statement
cursor.execute("SELECT * FROM location")

# Commit your changes if writing
# In this case, we are only reading data
# db.commit()

# Get the number of rows in the resultset
numrows = cursor.rowcount

# Get and display one row at a time
for x in range(0, numrows):
    row = cursor.fetchone()
    print row[0], "-->", row[1]

# Close the connection
db.close()

这里参考

Here’s one way to do it, using MySQLdb, which only supports Python 2:

#!/usr/bin/python
import MySQLdb

# Connect
db = MySQLdb.connect(host="localhost",
                     user="appuser",
                     passwd="",
                     db="onco")

cursor = db.cursor()

# Execute SQL select statement
cursor.execute("SELECT * FROM location")

# Commit your changes if writing
# In this case, we are only reading data
# db.commit()

# Get the number of rows in the resultset
numrows = cursor.rowcount

# Get and display one row at a time
for x in range(0, numrows):
    row = cursor.fetchone()
    print row[0], "-->", row[1]

# Close the connection
db.close()

Reference here


回答 2

Oracle(MySQL)现在支持纯Python连接器。这意味着无需安装任何二进制文件:它只是一个Python库。它称为“连接器/ Python”。

http://dev.mysql.com/downloads/connector/python/

Oracle (MySQL) now supports a pure Python connector. That means no binaries to install: it’s just a Python library. It’s called “Connector/Python”.

http://dev.mysql.com/downloads/connector/python/


回答 3

如果您不需要MySQLdb,但是可以接受任何库,那么我将非常非常推荐MySQL的MySQL Connector / Python:http : //dev.mysql.com/downloads/connector/python/

它是一个软件包(大约110k),是纯Python,因此它与系统无关,并且安装非常简单。您只需下载,双击,确认许可协议即可。无需Xcode,MacPorts,编译,重新启动……

然后,您像这样连接:

import mysql.connector    
cnx = mysql.connector.connect(user='scott', password='tiger',
                              host='127.0.0.1',
                              database='employees')

try:
   cursor = cnx.cursor()
   cursor.execute("""
      select 3 from your_table
   """)
   result = cursor.fetchall()
   print result
finally:
    cnx.close()

If you do not need MySQLdb, but would accept any library, I would very, very much recommend MySQL Connector/Python from MySQL: http://dev.mysql.com/downloads/connector/python/.

It is one package (around 110k), pure Python, so it is system independent, and dead simple to install. You just download, double-click, confirm license agreement and go. There is no need for Xcode, MacPorts, compiling, restarting …

Then you connect like:

import mysql.connector    
cnx = mysql.connector.connect(user='scott', password='tiger',
                              host='127.0.0.1',
                              database='employees')

try:
   cursor = cnx.cursor()
   cursor.execute("""
      select 3 from your_table
   """)
   result = cursor.fetchall()
   print result
finally:
    cnx.close()

回答 4

如果要避免安装mysql标头只是为了从python访问mysql,请停止使用MySQLDb。

使用pymysql。它可以完成MySQLDb的所有工作,但是它完全是在Python中实现的,没有外部依赖项。这使所有操作系统上的安装过程一致且容易。 pymysql是代替MySQLDb和恕我直言的替代品,没有理由将MySQLDb用于任何用途…永远!- PTSD from installing MySQLDb on Mac OSX and *Nix systems,但那只是我。

安装

pip install pymysql

就这样…您已经准备好玩了。

pymysql Github仓库的示例用法

import pymysql.cursors
import pymysql

# Connect to the database
connection = pymysql.connect(host='localhost',
                             user='user',
                             password='passwd',
                             db='db',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

try:
    with connection.cursor() as cursor:
        # Create a new record
        sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
        cursor.execute(sql, ('webmaster@python.org', 'very-secret'))

    # connection is not autocommit by default. So you must commit to save
    # your changes.
    connection.commit()

    with connection.cursor() as cursor:
        # Read a single record
        sql = "SELECT `id`, `password` FROM `users` WHERE `email`=%s"
        cursor.execute(sql, ('webmaster@python.org',))
        result = cursor.fetchone()
        print(result)
finally:
    connection.close()

还-快速,透明地替换现有代码中的MySQLdb

如果您已有使用MySQLdb的代码,则可以使用以下简单过程将其轻松替换为pymysql:

# import MySQLdb << Remove this line and replace with:
import pymysql
pymysql.install_as_MySQLdb()

所有后续对MySQLdb的引用将透明地使用pymysql。

Stop Using MySQLDb if you want to avoid installing mysql headers just to access mysql from python.

Use pymysql. It does all of what MySQLDb does, but it was implemented purely in Python with NO External Dependencies. This makes the installation process on all operating systems consistent and easy. pymysql is a drop in replacement for MySQLDb and IMHO there is no reason to ever use MySQLDb for anything… EVER! – PTSD from installing MySQLDb on Mac OSX and *Nix systems, but that’s just me.

Installation

pip install pymysql

That’s it… you are ready to play.

Example usage from pymysql Github repo

import pymysql.cursors
import pymysql

# Connect to the database
connection = pymysql.connect(host='localhost',
                             user='user',
                             password='passwd',
                             db='db',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

try:
    with connection.cursor() as cursor:
        # Create a new record
        sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
        cursor.execute(sql, ('webmaster@python.org', 'very-secret'))

    # connection is not autocommit by default. So you must commit to save
    # your changes.
    connection.commit()

    with connection.cursor() as cursor:
        # Read a single record
        sql = "SELECT `id`, `password` FROM `users` WHERE `email`=%s"
        cursor.execute(sql, ('webmaster@python.org',))
        result = cursor.fetchone()
        print(result)
finally:
    connection.close()

ALSO – Replace MySQLdb in existing code quickly and transparently

If you have existing code that uses MySQLdb, you can easily replace it with pymysql using this simple process:

# import MySQLdb << Remove this line and replace with:
import pymysql
pymysql.install_as_MySQLdb()

All subsequent references to MySQLdb will use pymysql transparently.


回答 5

尝试使用MySQLdb。MySQLdb仅支持Python 2。

这里有一个如何分页的方法:http : //www.kitebird.com/articles/pydbapi.html


从页面:

# server_version.py - retrieve and display database server version

import MySQLdb

conn = MySQLdb.connect (host = "localhost",
                        user = "testuser",
                        passwd = "testpass",
                        db = "test")
cursor = conn.cursor ()
cursor.execute ("SELECT VERSION()")
row = cursor.fetchone ()
print "server version:", row[0]
cursor.close ()
conn.close ()

Try using MySQLdb. MySQLdb only supports Python 2.

There is a how to page here: http://www.kitebird.com/articles/pydbapi.html


From the page:

# server_version.py - retrieve and display database server version

import MySQLdb

conn = MySQLdb.connect (host = "localhost",
                        user = "testuser",
                        passwd = "testpass",
                        db = "test")
cursor = conn.cursor ()
cursor.execute ("SELECT VERSION()")
row = cursor.fetchone ()
print "server version:", row[0]
cursor.close ()
conn.close ()

回答 6

作为数据库驱动程序,还有oursql。该链接上列出的一些原因说明了为什么我们的sql更好:

  • oursql具有真正的参数化功能,可将SQL和数据完全分别发送到MySQL。
  • oursql允许将文本或二进制数据流式传输到数据库中并从数据库中流式传输出来,而不需要将所有内容都缓存在客户端中。
  • oursql既可以延迟插入行,也可以延迟获取行。
  • oursql默认情况下启用unicode支持。
  • oursql支持python 2.4到2.7,在2.6+上没有任何弃用警告(请参阅PEP 218),在2.7上也没有完全失败(请参阅PEP 328)。
  • oursql在python 3.x上本地运行。

那么如何使用oursql连接到mysql?

与mysqldb非常相似:

import oursql

db_connection = oursql.connect(host='127.0.0.1',user='foo',passwd='foobar',db='db_name')
cur=db_connection.cursor()
cur.execute("SELECT * FROM `tbl_name`")
for row in cur.fetchall():
    print row[0]

文档中教程相当不错。

当然,对于ORM,SQLAlchemy是一个不错的选择,正如其他答案中已经提到的那样。

As a db driver, there is also oursql. Some of the reasons listed on that link, which say why oursql is better:

  • oursql has real parameterization, sending the SQL and data to MySQL completely separately.
  • oursql allows text or binary data to be streamed into the database and streamed out of the database, instead of requiring everything to be buffered in the client.
  • oursql can both insert rows lazily and fetch rows lazily.
  • oursql has unicode support on by default.
  • oursql supports python 2.4 through 2.7 without any deprecation warnings on 2.6+ (see PEP 218) and without completely failing on 2.7 (see PEP 328).
  • oursql runs natively on python 3.x.

So how to connect to mysql with oursql?

Very similar to mysqldb:

import oursql

db_connection = oursql.connect(host='127.0.0.1',user='foo',passwd='foobar',db='db_name')
cur=db_connection.cursor()
cur.execute("SELECT * FROM `tbl_name`")
for row in cur.fetchall():
    print row[0]

The tutorial in the documentation is pretty decent.

And of course for ORM SQLAlchemy is a good choice, as already mentioned in the other answers.


回答 7

在终端中运行以下命令以安装mysql连接器:

pip install mysql-connector-python

并在python编辑器中运行此命令以连接到MySQL:

import mysql.connector

mydb = mysql.connector.connect(
      host="localhost",
      user="yusername",
      passwd="password",
      database="database_name"
)

执行MySQL命令的示例(在python edior中):

mycursor = mydb.cursor()
mycursor.execute("CREATE TABLE customers (name VARCHAR(255), address VARCHAR(255))")    
mycursor.execute("SHOW TABLES")

mycursor.execute("INSERT INTO customers (name, address) VALUES ('John', 'Highway 21')")    
mydb.commit() # Use this command after insert or update

有关更多命令:https : //www.w3schools.com/python/python_mysql_getstarted.asp

Run this command in your terminal to install mysql connector:

pip install mysql-connector-python

And run this in your python editor to connect to MySQL:

import mysql.connector

mydb = mysql.connector.connect(
      host="localhost",
      user="yusername",
      passwd="password",
      database="database_name"
)

Samples to execute MySQL Commands (in your python edior):

mycursor = mydb.cursor()
mycursor.execute("CREATE TABLE customers (name VARCHAR(255), address VARCHAR(255))")    
mycursor.execute("SHOW TABLES")

mycursor.execute("INSERT INTO customers (name, address) VALUES ('John', 'Highway 21')")    
mydb.commit() # Use this command after insert or update

For more commands: https://www.w3schools.com/python/python_mysql_getstarted.asp


回答 8

SqlAlchemy的


SQLAlchemy是Python SQL工具箱和对象关系映射器,它为应用程序开发人员提供了SQL的全部功能和灵活性。SQLAlchemy提供了一整套著名的企业级持久性模式,旨在用于高效和高性能的数据库访问,并被适配为简单的Pythonic域语言。

安装

pip install sqlalchemy

RAW查询

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

engine = create_engine("mysql://<user_name>:<password>@<host_name>/<db_name>")
session_obj = sessionmaker(bind=engine)
session = scoped_session(session_obj)

# insert into database
session.execute("insert into person values(2, 'random_name')")
session.flush()
session.commit()

ORM方式

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

Base = declarative_base()
engine = create_engine("mysql://<user_name>:<password>@<host_name>/<db_name>")
session_obj = sessionmaker(bind=engine)
session = scoped_session(session_obj)

# Bind the engine to the metadata of the Base class so that the
# declaratives can be accessed through a DBSession instance
Base.metadata.bind = engine

class Person(Base):
    __tablename__ = 'person'
    # Here we define columns for the table person
    # Notice that each column is also a normal Python instance attribute.
    id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False)

# insert into database
person_obj = Person(id=12, name="name")
session.add(person_obj)
session.flush()
session.commit()

SqlAlchemy


SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL. SQLAlchemy provides a full suite of well known enterprise-level persistence patterns, designed for efficient and high-performing database access, adapted into a simple and Pythonic domain language.

Installation

pip install sqlalchemy

RAW query

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

engine = create_engine("mysql://<user_name>:<password>@<host_name>/<db_name>")
session_obj = sessionmaker(bind=engine)
session = scoped_session(session_obj)

# insert into database
session.execute("insert into person values(2, 'random_name')")
session.flush()
session.commit()

ORM way

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

Base = declarative_base()
engine = create_engine("mysql://<user_name>:<password>@<host_name>/<db_name>")
session_obj = sessionmaker(bind=engine)
session = scoped_session(session_obj)

# Bind the engine to the metadata of the Base class so that the
# declaratives can be accessed through a DBSession instance
Base.metadata.bind = engine

class Person(Base):
    __tablename__ = 'person'
    # Here we define columns for the table person
    # Notice that each column is also a normal Python instance attribute.
    id = Column(Integer, primary_key=True)
    name = Column(String(250), nullable=False)

# insert into database
person_obj = Person(id=12, name="name")
session.add(person_obj)
session.flush()
session.commit()

回答 9

尽管有上述所有答案,但是如果您不想预先连接到特定的数据库,例如,如果您仍要创建数据库(!),则可以使用connection.select_db(database),如下所示。

import pymysql.cursors
connection = pymysql.connect(host='localhost',
                         user='mahdi',
                         password='mahdi',
                         charset='utf8mb4',
                         cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
cursor.execute("CREATE DATABASE IF NOT EXISTS "+database)
connection.select_db(database)
sql_create = "CREATE TABLE IF NOT EXISTS "+tablename+(timestamp DATETIME NOT NULL PRIMARY KEY)"
cursor.execute(sql_create)
connection.commit()
cursor.close()

Despite all answers above, in case you do not want to connect to a specific database upfront, for example, if you want to create the database still (!), you can use connection.select_db(database), as demonstrated in the following.

import pymysql.cursors
connection = pymysql.connect(host='localhost',
                         user='mahdi',
                         password='mahdi',
                         charset='utf8mb4',
                         cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
cursor.execute("CREATE DATABASE IF NOT EXISTS "+database)
connection.select_db(database)
sql_create = "CREATE TABLE IF NOT EXISTS "+tablename+(timestamp DATETIME NOT NULL PRIMARY KEY)"
cursor.execute(sql_create)
connection.commit()
cursor.close()

回答 10

MySQLdb是直接的方法。您可以通过连接执行SQL查询。期。

我首选的方法也是pythonic,而是使用强大的SQLAlchemy。这是与查询相关的教程,这是有关SQLALchemy的ORM功能的教程。

MySQLdb is the straightforward way. You get to execute SQL queries over a connection. Period.

My preferred way, which is also pythonic, is to use the mighty SQLAlchemy instead. Here is a query related tutorial, and here is a tutorial on ORM capabilities of SQLALchemy.


回答 11

对于Python3.6,我发现了两个驱动程序:pymysql和mysqlclient。我测试了它们之间的性能并得到了结果:mysqlclient更快。

以下是我的测试过程(需要安装python lib profilehooks来分析时间流逝:

原始SQL: select * from FOO;

在mysql终端中立即执行: 46410 rows in set (0.10 sec)

pymysql(2.4秒):

from profilehooks import profile
import pymysql.cursors
import pymysql
connection = pymysql.connect(host='localhost', user='root', db='foo')
c = connection.cursor()

@profile(immediate=True)
def read_by_pymysql():
    c.execute("select * from FOO;")
    res = c.fetchall()

read_by_pymysql()

这是pymysql配置文件: 在此处输入图片说明


mysqlclient(0.4秒)

from profilehooks import profile
import MySQLdb

connection = MySQLdb.connect(host='localhost', user='root', db='foo')
c = connection.cursor()

@profile(immediate=True)
def read_by_mysqlclient():
    c.execute("select * from FOO;")
    res = c.fetchall()

read_by_mysqlclient()

这是mysqlclient配置文件: 在此处输入图片说明

因此,似乎mysqlclient比pymysql快得多

for Python3.6 I found two driver: pymysql and mysqlclient. I tested the performance between them and got the result: the mysqlclient is faster.

below is my test process(need install python lib profilehooks to analyze time elapse:

raw sql: select * from FOO;

immediatly execute in mysql terminal: 46410 rows in set (0.10 sec)

pymysql (2.4s):

from profilehooks import profile
import pymysql.cursors
import pymysql
connection = pymysql.connect(host='localhost', user='root', db='foo')
c = connection.cursor()

@profile(immediate=True)
def read_by_pymysql():
    c.execute("select * from FOO;")
    res = c.fetchall()

read_by_pymysql()

here’s the pymysql profile: enter image description here


mysqlclient (0.4s)

from profilehooks import profile
import MySQLdb

connection = MySQLdb.connect(host='localhost', user='root', db='foo')
c = connection.cursor()

@profile(immediate=True)
def read_by_mysqlclient():
    c.execute("select * from FOO;")
    res = c.fetchall()

read_by_mysqlclient()

here’s the mysqlclient profile: enter image description here

So, it seems that mysqlclient is much faster than pymysql


回答 12

从python连接到MySQL的最佳方法是使用MySQL Connector / Python,因为它是MySQL的正式Oracle驱动程序,可与Python一起使用,并且可与Python 3和Python 2一起使用。

按照下面提到的步骤连接MySQL

  1. 使用pip安装连接器

    pip install mysql-connector-python

或者您可以从https://dev.mysql.com/downloads/connector/python/下载安装程序

  1. 使用connect()mysql连接器python的method连接到MySQL。将所需的参数传递给connect()method。即主机,用户名,密码和数据库名称。

  2. cursorconnect()方法返回的连接对象创建对象以执行SQL查询。

  3. 工作完成后,关闭连接。

范例

import mysql.connector
 from mysql.connector import Error
 try:
     conn = mysql.connector.connect(host='hostname',
                         database='db',
                         user='root',
                         password='passcode')
     if conn.is_connected():
       cursor = conn.cursor()
       cursor.execute("select database();")
       record = cursor.fetchall()
       print ("You're connected to - ", record)
 except Error as e :
    print ("Print your error msg", e)
 finally:
    #closing database connection.
    if(conn.is_connected()):
       cursor.close()
       conn.close()

参考-https: //pynative.com/python-mysql-database-connection/

MySQL Connector Python的重要API

  • 对于DML操作-使用cursor.execute()cursor.executemany()运行查询。并connection.commit()用于保留对数据库的更改之后

  • 要获取数据-使用cursor.execute()运行查询cursor.fetchall()cursor.fetchone()cursor.fetchmany(SIZE)获取数据

Best way to connect to MySQL from python is to Use MySQL Connector/Python because it is official Oracle driver for MySQL for working with Python and it works with both Python 3 and Python 2.

follow the steps mentioned below to connect MySQL

  1. install connector using pip

    pip install mysql-connector-python

or you can download the installer from https://dev.mysql.com/downloads/connector/python/

  1. Use connect() method of mysql connector python to connect to MySQL.pass the required argument to connect() method. i.e. Host, username, password, and database name.

  2. Create cursor object from connection object returned by connect()method to execute SQL queries.

  3. close the connection after your work completes.

Example:

import mysql.connector
 from mysql.connector import Error
 try:
     conn = mysql.connector.connect(host='hostname',
                         database='db',
                         user='root',
                         password='passcode')
     if conn.is_connected():
       cursor = conn.cursor()
       cursor.execute("select database();")
       record = cursor.fetchall()
       print ("You're connected to - ", record)
 except Error as e :
    print ("Print your error msg", e)
 finally:
    #closing database connection.
    if(conn.is_connected()):
       cursor.close()
       conn.close()

Reference – https://pynative.com/python-mysql-database-connection/

Important API of MySQL Connector Python

  • For DML operations – Use cursor.execute() and cursor.executemany() to run query. and after this use connection.commit() to persist your changes to DB

  • To fetch data – Use cursor.execute() to run query and cursor.fetchall(), cursor.fetchone(), cursor.fetchmany(SIZE) to fetch data


回答 13

只是以上答案的修改。只需运行此命令即可为python安装mysql

sudo yum install MySQL-python
sudo apt-get install MySQL-python

记得!区分大小写。

Just a modification in above answer. Simply run this command to install mysql for python

sudo yum install MySQL-python
sudo apt-get install MySQL-python

remember! It is case sensitive.


回答 14

mysqlclient是最好的,因为其他人仅提供对特定版本的python的支持

 pip install mysqlclient

示例代码

    import mysql.connector
    import _mysql
    db=_mysql.connect("127.0.0.1","root","umer","sys")
    #db=_mysql.connect(host,user,password,db)
    # Example of how to insert new values:
    db.query("""INSERT INTO table1 VALUES ('01', 'myname')""")
    db.store_result()
    db.query("SELECT * FROM new1.table1 ;") 
    #new1 is scheme table1 is table mysql 
    res= db.store_result()
    for i in range(res.num_rows()):
        print(result.fetch_row())

参见https://github.com/PyMySQL/mysqlclient-python

mysqlclient is the best as others only provide support to specific versions of python

 pip install mysqlclient

example code

    import mysql.connector
    import _mysql
    db=_mysql.connect("127.0.0.1","root","umer","sys")
    #db=_mysql.connect(host,user,password,db)
    # Example of how to insert new values:
    db.query("""INSERT INTO table1 VALUES ('01', 'myname')""")
    db.store_result()
    db.query("SELECT * FROM new1.table1 ;") 
    #new1 is scheme table1 is table mysql 
    res= db.store_result()
    for i in range(res.num_rows()):
        print(result.fetch_row())

see https://github.com/PyMySQL/mysqlclient-python


回答 15

尽管有些人可能标志着其视为重复和生气,我复制别人的答案,我真的想强调Napik先生的回应的一个方面。因为错过了,导致全国网站停机(9分钟)。如果只有某人共享此信息,则可以避免!

这是他的代码:

import mysql.connector    
cnx = mysql.connector.connect(user='scott', password='tiger',
                              host='127.0.0.1',
                              database='employees')
try:
   cursor = cnx.cursor()
   cursor.execute("""select 3 from your_table""")
   result = cursor.fetchall()
   print(result)
finally:
    cnx.close()

这里重要的是Try and Final子句。这允许始终连接,无论代码的游标/ sqlstatement部分发生了什么,都可以关闭与之的。许多活动的连接会导致DBLoadNoCPU尖峰,并可能导致数据库服务器崩溃。

我希望此警告有助于节省服务器并最终节省工作!:D

Even though some of you may mark this as a duplicate and get upset that I am copying someone else’s answer, I would REALLY like to highlight an aspect of Mr. Napik’s response. Because I missed this, I caused nationwide website downtime (9min). If only someone shared this information, I could have prevented it!

Here is his code:

import mysql.connector    
cnx = mysql.connector.connect(user='scott', password='tiger',
                              host='127.0.0.1',
                              database='employees')
try:
   cursor = cnx.cursor()
   cursor.execute("""select 3 from your_table""")
   result = cursor.fetchall()
   print(result)
finally:
    cnx.close()

The important thing here is the Try and Finally clause. This allows connections to ALWAYS be closed, regardless of what happens in the cursor/sqlstatement portion of the code. A lot of active connections cause DBLoadNoCPU to spike and could crash a db server.

I hope this warning helps to save servers and ultimately jobs! :D


回答 16

也看看暴风雨。它是一个简单的SQL映射工具,可让您轻松编写和创建SQL条目,而无需编写查询。

这是一个简单的示例:

from storm.locals import *

# User will be the mapped object; you have to create the table before mapping it
class User(object):
        __storm_table__ = "user" # table name
        ID = Int(primary=True) #field ID
        name= Unicode() # field name

database = create_database("mysql://root:password@localhost:3306/databaseName")
store = Store(database)

user = User()
user.name = u"Mark"

print str(user.ID) # None

store.add(user)  
store.flush() # ID is AUTO_INCREMENT

print str(user.ID) # 1 (ID)

store.commit() # commit all changes to the database

查找并反对使用:

michael = store.find(User, User.name == u"Michael").one()
print str(user.ID) # 10

使用主键查找:

print store.get(User, 1).name #Mark

有关更多信息,请参见教程

Also take a look at Storm. It is a simple SQL mapping tool which allows you to easily edit and create SQL entries without writing the queries.

Here is a simple example:

from storm.locals import *

# User will be the mapped object; you have to create the table before mapping it
class User(object):
        __storm_table__ = "user" # table name
        ID = Int(primary=True) #field ID
        name= Unicode() # field name

database = create_database("mysql://root:password@localhost:3306/databaseName")
store = Store(database)

user = User()
user.name = u"Mark"

print str(user.ID) # None

store.add(user)  
store.flush() # ID is AUTO_INCREMENT

print str(user.ID) # 1 (ID)

store.commit() # commit all changes to the database

To find and object use:

michael = store.find(User, User.name == u"Michael").one()
print str(user.ID) # 10

Find with primary key:

print store.get(User, 1).name #Mark

For further information see the tutorial.


回答 17

这是Mysql DB连接

from flask import Flask, render_template, request
from flask_mysqldb import MySQL

app = Flask(__name__)


app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'root'
app.config['MYSQL_DB'] = 'MyDB'

mysql = MySQL(app)


@app.route('/', methods=['GET', 'POST']) 
def index():
    if request.method == "POST":
        details = request.form
        cur = mysql.connection.cursor()
        cur.execute ("_Your query_")
        mysql.connection.commit()
        cur.close()
        return 'success'
    return render_template('index.html')


if __name__ == '__main__':
    app.run()

This is Mysql DB connection

from flask import Flask, render_template, request
from flask_mysqldb import MySQL

app = Flask(__name__)


app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'root'
app.config['MYSQL_DB'] = 'MyDB'

mysql = MySQL(app)


@app.route('/', methods=['GET', 'POST']) 
def index():
    if request.method == "POST":
        details = request.form
        cur = mysql.connection.cursor()
        cur.execute ("_Your query_")
        mysql.connection.commit()
        cur.close()
        return 'success'
    return render_template('index.html')


if __name__ == '__main__':
    app.run()

回答 18

首先安装驱动程序

pip install MySQL-python   

然后,基本代码如下所示:

#!/usr/bin/python
import MySQLdb

try:
    db = MySQLdb.connect(host="localhost",      # db server, can be a remote one 
                     db="mydb"                  # database
                     user="mydb",               # username
                     passwd="mydb123",          # password for this username
                     )        

    # Create a Cursor object
    cur = db.cursor()

    # Create a query string. It can contain variables
    query_string = "SELECT * FROM MY_TABLE"

    # Execute the query
    cur.execute(query_string)

    # Get all the rows present the database
    for each_row in cur.fetchall():
        print each_row

    # Close the connection
    db.close()
except Exception, e:
    print 'Error ', e 

first install the driver

pip install MySQL-python   

Then a basic code goes like this:

#!/usr/bin/python
import MySQLdb

try:
    db = MySQLdb.connect(host="localhost",      # db server, can be a remote one 
                     db="mydb"                  # database
                     user="mydb",               # username
                     passwd="mydb123",          # password for this username
                     )        

    # Create a Cursor object
    cur = db.cursor()

    # Create a query string. It can contain variables
    query_string = "SELECT * FROM MY_TABLE"

    # Execute the query
    cur.execute(query_string)

    # Get all the rows present the database
    for each_row in cur.fetchall():
        print each_row

    # Close the connection
    db.close()
except Exception, e:
    print 'Error ', e 

回答 19

您可以通过这种方式将python代码连接到mysql。

import MySQLdb
db = MySQLdb.connect(host="localhost",
                 user="appuser",
                 passwd="",
                 db="onco")

cursor = db.cursor()

you can connect your python code to mysql in this way.

import MySQLdb
db = MySQLdb.connect(host="localhost",
                 user="appuser",
                 passwd="",
                 db="onco")

cursor = db.cursor()

回答 20

首先安装驱动程序(Ubuntu)

  • 须藤apt-get install python-pip

  • sudo pip install -U pip

  • 须藤apt-get install python-dev libmysqlclient-dev

  • sudo apt-get安装MySQL-python

MySQL数据库连接代码

import MySQLdb
conn = MySQLdb.connect (host = "localhost",user = "root",passwd = "pass",db = "dbname")
cursor = conn.cursor ()
cursor.execute ("SELECT VERSION()")
row = cursor.fetchone ()
print "server version:", row[0]
cursor.close ()
conn.close ()

First install the driver (Ubuntu)

  • sudo apt-get install python-pip

  • sudo pip install -U pip

  • sudo apt-get install python-dev libmysqlclient-dev

  • sudo apt-get install MySQL-python

MySQL database connection codes

import MySQLdb
conn = MySQLdb.connect (host = "localhost",user = "root",passwd = "pass",db = "dbname")
cursor = conn.cursor ()
cursor.execute ("SELECT VERSION()")
row = cursor.fetchone ()
print "server version:", row[0]
cursor.close ()
conn.close ()

回答 21

对于python 3.3

CyMySQL https://github.com/nakagami/CyMySQL

我在Windows 7上安装了pip,只需pip install cymysql

(您不需要赛顿)快速而无痛

For python 3.3

CyMySQL https://github.com/nakagami/CyMySQL

I have pip installed on my windows 7, just pip install cymysql

(you don’t need cython) quick and painless


回答 22

首先,从https://dev.mysql.com/downloads/connector/python/安装python-mysql连接器

在Python控制台上输入:

pip install mysql-connector-python-rf
import mysql.connector

First, install python-mysql connector from https://dev.mysql.com/downloads/connector/python/

on Python console enter:

pip install mysql-connector-python-rf
import mysql.connector

有没有办法在Python中创建多行注释?

问题:有没有办法在Python中创建多行注释?

我最近开始研究Python,但是找不到如何实现多行注释。大多数语言都有块注释符号,例如

/*

*/

我在Python中尝试过此方法,但它引发了错误,因此这可能不是正确的方法。Python实际上是否具有多行注释功能?

I have recently started studying Python, but I couldn’t find how to implement multi-line comments. Most languages have block comment symbols like

/*

*/

I tried this in Python, but it throws an error, so this probably is not the correct way. Does Python actually have a multiline comment feature?


回答 0

您可以使用三引号引起来的字符串。如果它们不是文档字符串(类/函数/模块中的第一件事),则将其忽略。

'''
This is a multiline
comment.
'''

(请确保'''适当缩进引线,以避免出现IndentationError。)

Guido van Rossum(Python的创建者)在推特上发了一条“专业提示”。

但是,Python的样式指南PEP8 倾向于使用连续的单行注释,这也是在许多项目中都可以找到的。文本编辑器通常具有快捷方式来轻松实现此目的。

You can use triple-quoted strings. When they’re not a docstring (the first thing in a class/function/module), they are ignored.

'''
This is a multiline
comment.
'''

(Make sure to indent the leading ''' appropriately to avoid an IndentationError.)

Guido van Rossum (creator of Python) tweeted this as a “pro tip”.

However, Python’s style guide, PEP8, favors using consecutive single-line comments, and this is also what you’ll find in many projects. Text editors usually have a shortcut to do this easily.


回答 1

从某种意义上说,Python确实具有多行字符串/注释语法,除非多行字符串不用作文档字符串,否则不会生成字节码 -就像- #前置注释一样。实际上,它的行为就像评论一样。

另一方面,如果您说必须在官方文档中记录此行为才是真正的注释语法,那么可以,您可以肯定地说这不是语言规范的一部分。

无论如何,您的文本编辑器还应该能够轻松注释掉所选区域(通过#在每个行的前面分别放置一个)。如果不是,请切换到可以的文本编辑器。

没有某些文本编辑功能的Python编程可能会很痛苦。找到合适的编辑器(并知道如何使用它)可以在如何理解Python编程经验方面产生很大的不同。

文本编辑器不仅能够注释掉选定的区域,还应该能够轻松地向左和向右移动代码块,并且当您按时它应该自动将光标置于当前的缩进级别Enter。代码折叠也很有用。


为了防止链路衰减,这是Guido van Rossum的推文的内容

@BSUCSClub Python提示:您可以将多行字符串用作多行注释。除非用作文档字符串,否则它们不会生成任何代码!:-)

Python does have a multiline string/comment syntax in the sense that unless used as docstrings, multiline strings generate no bytecode — just like #-prepended comments. In effect, it acts exactly like a comment.

On the other hand, if you say this behavior must be documented in the official documentation to be a true comment syntax, then yes, you would be right to say it is not guaranteed as part of the language specification.

In any case, your text editor should also be able to easily comment-out a selected region (by placing a # in front of each line individually). If not, switch to a text editor that does.

Programming in Python without certain text editing features can be a painful experience. Finding the right editor (and knowing how to use it) can make a big difference in how the Python programming experience is perceived.

Not only should the text editor be able to comment-out selected regions, it should also be able to shift blocks of code to the left and right easily, and it should automatically place the cursor at the current indentation level when you press Enter. Code folding can also be useful.


To protect against link decay, here is the content of Guido van Rossum’s tweet:

@BSUCSClub Python tip: You can use multi-line strings as multi-line comments. Unless used as docstrings, they generate no code! :-)


回答 2

从接受的答案…

您可以使用三引号引起来的字符串。如果它们不是文档字符串(类/函数/模块中的第一件事),则将其忽略。

这是不正确的。与注释不同,三引号字符串仍然会被解析,并且在语法上必须有效,无论它们在源代码中的位置如何。

如果您尝试运行此代码…

def parse_token(token):
    """
    This function parses a token.
    TODO: write a decent docstring :-)
    """

    if token == '\\and':
        do_something()

    elif token == '\\or':
        do_something_else()

    elif token == '\\xor':
        '''
        Note that we still need to provide support for the deprecated
        token \xor. Hopefully we can drop support in libfoo 2.0.
        '''
        do_a_different_thing()

    else:
        raise ValueError

你会得到…

ValueError: invalid \x escape

…在Python 2.x上…

SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 79-80: truncated \xXX escape

…在Python 3.x上。

进行解析器忽略的多行注释的唯一方法是…

elif token == '\\xor':
    # Note that we still need to provide support for the deprecated
    # token \xor. Hopefully we can drop support in libfoo 2.0.
    do_a_different_thing()

From the accepted answer…

You can use triple-quoted strings. When they’re not a docstring (first thing in a class/function/module), they are ignored.

This is simply not true. Unlike comments, triple-quoted strings are still parsed and must be syntactically valid, regardless of where they appear in the source code.

If you try to run this code…

def parse_token(token):
    """
    This function parses a token.
    TODO: write a decent docstring :-)
    """

    if token == '\\and':
        do_something()

    elif token == '\\or':
        do_something_else()

    elif token == '\\xor':
        '''
        Note that we still need to provide support for the deprecated
        token \xor. Hopefully we can drop support in libfoo 2.0.
        '''
        do_a_different_thing()

    else:
        raise ValueError

You’ll get either…

ValueError: invalid \x escape

…on Python 2.x or…

SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 79-80: truncated \xXX escape

…on Python 3.x.

The only way to do multi-line comments which are ignored by the parser is…

elif token == '\\xor':
    # Note that we still need to provide support for the deprecated
    # token \xor. Hopefully we can drop support in libfoo 2.0.
    do_a_different_thing()

回答 3

在Python 2.7中,多行注释为:

"""
This is a
multilline comment
"""

如果您在Class里,应该正确地选择它。

例如:

class weather2():
   """
   def getStatus_code(self, url):
       world.url = url
       result = requests.get(url)
       return result.status_code
   """

In Python 2.7 the multiline comment is:

"""
This is a
multilline comment
"""

In case you are inside a class you should tab it properly.

For example:

class weather2():
   """
   def getStatus_code(self, url):
       world.url = url
       result = requests.get(url)
       return result.status_code
   """

回答 4

AFAIK,Python没有阻止注释。要注释单个行,可以使用该#字符。

如果使用的是Notepad ++则有一个用于块注释的快捷方式。我敢肯定,像gVimEmacs这样的人也有类似的功能。

AFAIK, Python doesn’t have block comments. For commenting individual lines, you can use the # character.

If you are using Notepad++, there is a shortcut for block commenting. I’m sure others like gVim and Emacs have similar features.


回答 5

我认为没有,除了未处理多行字符串。但是,大多数(如果不是全部)Python IDE都具有用于“注释”多行代码的快捷键。

I think it doesn’t, except that a multiline string isn’t processed. However, most, if not all Python IDEs have a shortkey for ‘commenting out’ multiple lines of code.


回答 6

如果您发表评论

"""
long comment here
"""

在脚本中间,Python / lint无法识别。折叠将被弄乱,因为以上注释不是标准建议的一部分。最好用

# Long comment
# here.

如果使用Vim,则可以使用commentary.vim之类的插件通过按来自动注释掉较长的注释行Vjgcc。在其中Vj选择两行代码,并将gcc其注释掉。

如果您不想使用上述插件,则可以使用搜索和替换类似

:.,.+1s/^/# /g

这会将当前和下一行的第一个字符替换为#

If you put a comment in

"""
long comment here
"""

in the middle of a script, Python/linters won’t recognize that. Folding will be messed up, as the above comment is not part of the standard recommendations. It’s better to use

# Long comment
# here.

If you use Vim, you can plugins like commentary.vim, to automatically comment out long lines of comments by pressing Vjgcc. Where Vj selects two lines of code, and gcc comments them out.

If you don’t want to use plugins like the above you can use search and replace like

:.,.+1s/^/# /g

This will replace the first character on the current and next line with #.


回答 7

没有多行注释等功能。#是注释一行代码的唯一方法。你们中的许多人都回答”’评论”’作为他们的解决方案。

它似乎可行,但是'''在Python 内部,它使用常规字符串将封闭的行作为解释器不会忽略的注释之类的注释#

在此处查看官方文档

There is no such feature as a multi-line comment. # is the only way to comment a single line of code. Many of you answered ”’ a comment ”’ this as their solution.

It seems to work, but internally ''' in Python takes the lines enclosed as a regular strings which the interpreter does not ignores like comment using #.

Check the official documentation here


回答 8

不幸的是,字符串化不能总是用作注释!因此,更安全的做法是坚持在每行前面加一个#

这是一个例子:

test1 = [1, 2, 3, 4,]       # test1 contains 4 integers

test2 = [1, 2, '''3, 4,'''] # test2 contains 2 integers **and the string** '3, 4,'

Unfortunately stringification can not always be used as commenting out! So it is safer to stick to the standard prepending each line with a #.

Here is an example:

test1 = [1, 2, 3, 4,]       # test1 contains 4 integers

test2 = [1, 2, '''3, 4,'''] # test2 contains 2 integers **and the string** '3, 4,'

回答 9

好了,您可以尝试一下(在运行引号时,第一个问题的输入应用引号'):

"""
print("What's your name? ")
myName = input()
print("It's nice to meet you " + myName)
print("Number of characters is ")
print(len(myName))
age = input("What's your age? ")
print("You will be " + str(int(age)+1) + " next year.")

"""
a = input()
print(a)
print(a*5)

包括在内的任何内容"""都会被评论。

如果您要查找单行注释,则为#

Well, you can try this (when running the quoted, the input to the first question should quoted with '):

"""
print("What's your name? ")
myName = input()
print("It's nice to meet you " + myName)
print("Number of characters is ")
print(len(myName))
age = input("What's your age? ")
print("You will be " + str(int(age)+1) + " next year.")

"""
a = input()
print(a)
print(a*5)

Whatever enclosed between """ will be commented.

If you are looking for single-line comments then it’s #.


回答 10

Python中的多行注释:

对我来说,“”和“”都有效。

例:

a = 10
b = 20
c = a+b
'''
print ('hello')
'''
print ('Addition is: ', a+b)

例:

a = 10
b = 20
c = a+b
"""
print('hello')
"""
print('Addition is: ', a+b)

Multiline comment in Python:

For me, both ”’ and “”” worked.

Example:

a = 10
b = 20
c = a+b
'''
print ('hello')
'''
print ('Addition is: ', a+b)

Example:

a = 10
b = 20
c = a+b
"""
print('hello')
"""
print('Addition is: ', a+b)

回答 11

Python中的内联注释以井号字符开头。

hello = "Hello!" # This is an inline comment
print(hello)

你好!

请注意,字符串文字中的哈希字符只是哈希字符。

dial = "Dial #100 to make an emergency call."
print(dial)

拨打#100拨打紧急电话。

哈希字符也可以用于单行或多行注释。

hello = "Hello"
world = "World"
# First print hello
# And print world
print(hello)
print(world)

你好

世界

用三重双引号将文本括起来以支持文档字符串。

def say_hello(name):
    """
    This is docstring comment and
    it's support multi line.
    :param name it's your name
    :type name str
    """
    return "Hello " + name + '!'


print(say_hello("John"))

你好约翰!

将文本用三重单引号引起来以用于块注释。

'''
I don't care the parameters and
docstrings here.
'''

The inline comments in Python starts with a hash character.

hello = "Hello!" # This is an inline comment
print(hello)

Hello!

Note that a hash character within a string literal is just a hash character.

dial = "Dial #100 to make an emergency call."
print(dial)

Dial #100 to make an emergency call.

A hash character can also be used for single or multiple lines comments.

hello = "Hello"
world = "World"
# First print hello
# And print world
print(hello)
print(world)

Hello

World

Enclose the text with triple double quotes to support docstring.

def say_hello(name):
    """
    This is docstring comment and
    it's support multi line.
    :param name it's your name
    :type name str
    """
    return "Hello " + name + '!'


print(say_hello("John"))

Hello John!

Enclose the text with triple single quotes for block comments.

'''
I don't care the parameters and
docstrings here.
'''

回答 12

在Python 2.7.13上:

单:

"A sample single line comment "

多行:

"""
A sample
multiline comment
on PyCharm
"""

On Python 2.7.13:

Single:

"A sample single line comment "

Multiline:

"""
A sample
multiline comment
on PyCharm
"""

回答 13

Visual Studio Code通用官方多行注释切换。

macOS:选择代码块,然后+/

Windows:选择代码块,然后Ctrl+/

Visual Studio Code universal official multi-line comment toggle.

macOS: Select code-block and then +/

Windows: Select code-block and then Ctrl+/


回答 14

是的,可以同时使用以下两种:

'''
Comments
'''

"""
Comments
"""

但是,在IDE中运行时,您唯一需要记住的是,您必须“运行”整个文件才能被多行代码接受。逐行“运行”将无法正常工作,并会显示错误。

Yes, it is fine to use both:

'''
Comments
'''

and

"""
Comments
"""

But, the only thing you all need to remember while running in an IDE, is you have to ‘RUN’ the entire file to be accepted as multiple lines codes. Line by line ‘RUN’ won’t work properly and will show an error.


回答 15

要注释掉Python中的多行代码,只需#在每一行上使用单行注释:

# This is comment 1
# This is comment 2 
# This is comment 3

要在Python中编写“适当的”多行注释,是使用具有"""语法的多行字符串Python具有文档字符串(或文档字符串)功能。它为程序员提供了一种在每个Python模块,函数,类和方法中添加快速注释的简便方法。

'''
This is
multiline
comment
'''

另外,请注意,您可以通过这样的类对象访问docstring

myobj.__doc__

For commenting out multiple lines of code in Python is to simply use a # single-line comment on every line:

# This is comment 1
# This is comment 2 
# This is comment 3

For writing “proper” multi-line comments in Python is to use multi-line strings with the """ syntax Python has the documentation strings (or docstrings) feature. It gives programmers an easy way of adding quick notes with every Python module, function, class, and method.

'''
This is
multiline
comment
'''

Also, mention that you can access docstring by a class object like this

myobj.__doc__

回答 16

您可以使用以下内容。这称为DockString。

def my_function(arg1):
    """
    Summary line.
    Extended description of function.
    Parameters:
    arg1 (int): Description of arg1
    Returns:
    int: Description of return value
    """
    return arg1

print my_function.__doc__

You can use the following. This is called DockString.

def my_function(arg1):
    """
    Summary line.
    Extended description of function.
    Parameters:
    arg1 (int): Description of arg1
    Returns:
    int: Description of return value
    """
    return arg1

print my_function.__doc__

回答 17

我建议不要使用"""多行注释!

这是一个简单的示例,以突出显示可能被视为意外行为的内容:

print('{}\n{}'.format(
    'I am a string',
    """
    Some people consider me a
    multi-line comment, but
    """
    'clearly I am also a string'
    )
)

现在看一下输出:

I am a string

    Some people consider me a
    multi-line comment, but
    clearly I am also a string

多行字符串不被视为注释,而是与之连接'clearly I'm also a string'形成一个字符串。

如果要注释多行,请按照PEP 8准则进行注释

print('{}\n{}'.format(
    'I am a string',
    # Some people consider me a
    # multi-line comment, but
    'clearly I am also a string'
    )
)

输出:

I am a string
clearly I am also a string

I would advise against using """ for multi line comments!

Here is a simple example to highlight what might be considered an unexpected behavior:

print('{}\n{}'.format(
    'I am a string',
    """
    Some people consider me a
    multi-line comment, but
    """
    'clearly I am also a string'
    )
)

Now have a look at the output:

I am a string

    Some people consider me a
    multi-line comment, but
    clearly I am also a string

The multi line string was not treated as comment, but it was concatenated with 'clearly I'm also a string' to form a single string.

If you want to comment multiple lines do so according to PEP 8 guidelines:

print('{}\n{}'.format(
    'I am a string',
    # Some people consider me a
    # multi-line comment, but
    'clearly I am also a string'
    )
)

Output:

I am a string
clearly I am also a string

回答 18

使用PyCharm IDE。

您可以使用Ctrl + /commentuncomment代码行。Ctrl + /注释或取消注释当前行或用单行注释注释掉若干行({# in Django templates, or # in Python scripts)Pressing Ctrl+Shift+/对于Django模板中选定的源代码块,该块用{% comment %} and {% endcomment %}标签包围。


n = 5
while n > 0:
    n -= 1
    if n == 2:
        break
    print(n)

print("Loop ended.")

选择所有行,然后按 Ctrl + /


# n = 5
# while n > 0:
#     n -= 1
#     if n == 2:
#         break
#     print(n)

# print("Loop ended.")

Using PyCharm IDE.

You can comment and uncomment lines of code using Ctrl+/. Ctrl+/ comments or uncomments the current line or several selected lines with single line comments ({# in Django templates, or # in Python scripts). Pressing Ctrl+Shift+/ for a selected block of source code in a Django template surrounds the block with {% comment %} and {% endcomment %} tags.


n = 5
while n > 0:
    n -= 1
    if n == 2:
        break
    print(n)

print("Loop ended.")

Select all lines then press Ctrl + /


# n = 5
# while n > 0:
#     n -= 1
#     if n == 2:
#         break
#     print(n)

# print("Loop ended.")

回答 19

多行注释实际上在Python中不存在。下面的示例包含一个未分配的字符串,该字符串已通过Python验证是否存在语法错误。

一些文本编辑器,例如Notepad ++,为我们提供了注释掉一段书面代码或单词的快捷方式。

def foo():
    "This is a doc string."
    # A single line comment
    """
       This
       is a multiline
       comment/String
    """
    """
    print "This is a sample foo function"
    print "This function has no arguments"
    """
    return True

另外,Ctrl+ K是Notepad ++中阻止评论的快捷方式。它#在所选内容的每行前面添加一个。Ctrl+ Shift+ K用于取消注释。

A multiline comment doesn’t actually exist in Python. The below example consists of an unassigned string, which is validated by Python for syntactical errors.

A few text editors, like Notepad++, provide us shortcuts to comment out a written piece of code or words.

def foo():
    "This is a doc string."
    # A single line comment
    """
       This
       is a multiline
       comment/String
    """
    """
    print "This is a sample foo function"
    print "This function has no arguments"
    """
    return True

Also, Ctrl + K is a shortcut in Notepad++ to block comment. It adds a # in front of every line under the selection. Ctrl + Shift + K is for block uncomment.


回答 20

在其他答案中,我发现最简单的方法是使用IDE注释函数,该函数使用的Python注释支持#

我正在使用Anaconda Spyder,它具有:

  • Ctrl+ 1-评论/取消评论
  • Ctrl+ 4-注释一段代码
  • Ctrl+ 5-取消注释代码块

它将使用注释/取消注释单行/多行代码#

我觉得最简单。

例如,一个块注释:

# =============================================================================
#     Sample Commented code in spyder
#  Hello, World!
# =============================================================================

Among other answers, I find the easiest way is to use the IDE comment functions which use the Python comment support of #.

I am using Anaconda Spyder and it has:

  • Ctrl + 1 – Comment/uncomment
  • Ctrl + 4 – Comment a block of code
  • Ctrl + 5 – Uncomment a block of code

It would comment/uncomment a single/multi line/s of code with #.

I find it the easiest.

For example, a block comment:

# =============================================================================
#     Sample Commented code in spyder
#  Hello, World!
# =============================================================================

回答 21

选择要注释的行,然后使用Ctrl+ ?注释或取消注释Sublime Text中的Python代码。编辑器中。

对于单行,可以使用Shift+ #

Select the lines that you want to comment and then use Ctrl + ? to comment or uncomment the Python code in the Sublime Text editor.

For single line you can use Shift + #.