分类目录归档:知识问答

我如何避免“ self.x = x; self.y = y; __init__中的self.z = z”模式?

问题:我如何避免“ self.x = x; self.y = y; __init__中的self.z = z”模式?

我看到像

def __init__(self, x, y, z):
    ...
    self.x = x
    self.y = y
    self.z = z
    ...

非常频繁,通常带有更多参数。是否有避免这种乏味重复的好方法?该类应该继承namedtuple吗?

I see patterns like

def __init__(self, x, y, z):
    ...
    self.x = x
    self.y = y
    self.z = z
    ...

quite frequently, often with a lot more parameters. Is there a good way to avoid this type of tedious repetitiveness? Should the class inherit from namedtuple instead?


回答 0

编辑:如果您有python 3.7+,只需使用数据类

保留签名的装饰器解决方案:

import decorator
import inspect
import sys


@decorator.decorator
def simple_init(func, self, *args, **kws):
    """
    @simple_init
    def __init__(self,a,b,...,z)
        dosomething()

    behaves like

    def __init__(self,a,b,...,z)
        self.a = a
        self.b = b
        ...
        self.z = z
        dosomething()
    """

    #init_argumentnames_without_self = ['a','b',...,'z']
    if sys.version_info.major == 2:
        init_argumentnames_without_self = inspect.getargspec(func).args[1:]
    else:
        init_argumentnames_without_self = tuple(inspect.signature(func).parameters.keys())[1:]

    positional_values = args
    keyword_values_in_correct_order = tuple(kws[key] for key in init_argumentnames_without_self if key in kws)
    attribute_values = positional_values + keyword_values_in_correct_order

    for attribute_name,attribute_value in zip(init_argumentnames_without_self,attribute_values):
        setattr(self,attribute_name,attribute_value)

    # call the original __init__
    func(self, *args, **kws)


class Test():
    @simple_init
    def __init__(self,a,b,c,d=4):
        print(self.a,self.b,self.c,self.d)

#prints 1 3 2 4
t = Test(1,c=2,b=3)
#keeps signature
#prints ['self', 'a', 'b', 'c', 'd']
if sys.version_info.major == 2:
    print(inspect.getargspec(Test.__init__).args)
else:
    print(inspect.signature(Test.__init__))

Edit: If you have python 3.7+ just use dataclasses

A decorator solution that keeps the signature:

import decorator
import inspect
import sys


@decorator.decorator
def simple_init(func, self, *args, **kws):
    """
    @simple_init
    def __init__(self,a,b,...,z)
        dosomething()

    behaves like

    def __init__(self,a,b,...,z)
        self.a = a
        self.b = b
        ...
        self.z = z
        dosomething()
    """

    #init_argumentnames_without_self = ['a','b',...,'z']
    if sys.version_info.major == 2:
        init_argumentnames_without_self = inspect.getargspec(func).args[1:]
    else:
        init_argumentnames_without_self = tuple(inspect.signature(func).parameters.keys())[1:]

    positional_values = args
    keyword_values_in_correct_order = tuple(kws[key] for key in init_argumentnames_without_self if key in kws)
    attribute_values = positional_values + keyword_values_in_correct_order

    for attribute_name,attribute_value in zip(init_argumentnames_without_self,attribute_values):
        setattr(self,attribute_name,attribute_value)

    # call the original __init__
    func(self, *args, **kws)


class Test():
    @simple_init
    def __init__(self,a,b,c,d=4):
        print(self.a,self.b,self.c,self.d)

#prints 1 3 2 4
t = Test(1,c=2,b=3)
#keeps signature
#prints ['self', 'a', 'b', 'c', 'd']
if sys.version_info.major == 2:
    print(inspect.getargspec(Test.__init__).args)
else:
    print(inspect.signature(Test.__init__))

回答 1

免责声明:似乎有些人担心提出此解决方案,因此我将提供一个非常明确的免责声明。您不应该使用此解决方案。我仅将其作为信息提供,因此您知道该语言可以做到这一点。剩下的答案只是显示语言功能,而不是认可以这种方式使用它们。


明确地将参数复制到属性中并没有什么错。如果ctor中的参数太多,有时会被认为是代码异味,也许您应该将这些参数分组到更少的对象中。在其他时候,这是必要的,没有错。无论如何,明确地做到这一点是必须的。

但是,由于您要问如何完成(而不是是否应该这样做),因此一种解决方案是:

class A:
    def __init__(self, **kwargs):
        for key in kwargs:
          setattr(self, key, kwargs[key])

a = A(l=1, d=2)
a.l # will return 1
a.d # will return 2

Disclaimer: It seems that several people are concerned about presenting this solution, so I will provide a very clear disclaimer. You should not use this solution. I only provide it as information, so you know that the language is capable of this. The rest of the answer is just showing language capabilities, not endorsing using them in this way.


There isn’t really anything wrong with explicitly copying parameters into attributes. If you have too many parameters in the ctor, it is sometimes considered a code smell and maybe you should group these params into a fewer objects. Other times, it is necessary and there is nothing wrong with it. Anyway, doing it explicitly is the way to go.

However, since you are asking HOW it can be done (and not whether it should be done), then one solution is this:

class A:
    def __init__(self, **kwargs):
        for key in kwargs:
          setattr(self, key, kwargs[key])

a = A(l=1, d=2)
a.l # will return 1
a.d # will return 2

回答 2

正如其他人所提到的,重复并不坏,但在某些情况下,命名元组可能非常适合此类问题。这样可以避免使用locals()或kwargs,这通常不是一个好主意。

from collections import namedtuple
# declare a new object type with three properties; x y z
# the first arg of namedtuple is a typename
# the second arg is comma-separated or space-separated property names
XYZ = namedtuple("XYZ", "x, y, z")

# create an object of type XYZ. properties are in order
abc = XYZ("one", "two", 3)
print abc.x
print abc.y
print abc.z

我发现它的用途有限,但是您可以像其他任何对象一样继承一个namedtuple(示例继续):

class MySuperXYZ(XYZ):
    """ I add a helper function which returns the original properties """
    def properties(self):
        return self.x, self.y, self.z

abc2 = MySuperXYZ(4, "five", "six")
print abc2.x
print abc2.y
print abc2.z
print abc2.properties()

As others have mentioned, the repetition isn’t bad, but in some cases a namedtuple can be a great fit for this type of issue. This avoids using locals() or kwargs, which are usually a bad idea.

from collections import namedtuple
# declare a new object type with three properties; x y z
# the first arg of namedtuple is a typename
# the second arg is comma-separated or space-separated property names
XYZ = namedtuple("XYZ", "x, y, z")

# create an object of type XYZ. properties are in order
abc = XYZ("one", "two", 3)
print abc.x
print abc.y
print abc.z

I’ve found limited use for it, but you can inherit a namedtuple as with any other object (example continued):

class MySuperXYZ(XYZ):
    """ I add a helper function which returns the original properties """
    def properties(self):
        return self.x, self.y, self.z

abc2 = MySuperXYZ(4, "five", "six")
print abc2.x
print abc2.y
print abc2.z
print abc2.properties()

回答 3

显式比隐式更好…因此,请确保您可以使其更简洁:

def __init__(self,a,b,c):
    for k,v in locals().items():
        if k != "self":
             setattr(self,k,v)

更好的问题是您?

…这就是说,如果您想要一个命名元组,我建议您使用namedtuple(记住元组具有某些附加条件)…也许您想要一个有序的字典甚至是一个字典…

explicit is better than implicit … so sure you could make it more concise:

def __init__(self,a,b,c):
    for k,v in locals().items():
        if k != "self":
             setattr(self,k,v)

The better question is should you?

… that said if you want a named tuple I would recommend using a namedtuple (remember tuples have certain conditions attached to them) … perhaps you want an ordereddict or even just a dict …


回答 4

为了扩展gruszczys的答案,我使用了类似的模式:

class X:
    x = None
    y = None
    z = None
    def __init__(self, **kwargs):
        for (k, v) in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)
            else:
                raise TypeError('Unknown keyword argument: {:s}'.format(k))

我喜欢这种方法,因为它:

  • 避免重复
  • 构造对象时可以抵抗拼写错误
  • 可以很好地与子类化(只需super().__init(...)
  • 允许在类级别(它们所属的地方)而不是在 X.__init__

在Python 3.6之前,这无法控制属性的设置顺序,如果某些属性是带有访问其他属性的设置器的属性,则可能会出现问题。

可能会有所改善,但是我是我自己的代码的唯一用户,因此我不担心任何形式的输入卫生。也许AttributeError更合适。

To expand on gruszczys answer, I have used a pattern like:

class X:
    x = None
    y = None
    z = None
    def __init__(self, **kwargs):
        for (k, v) in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)
            else:
                raise TypeError('Unknown keyword argument: {:s}'.format(k))

I like this method because it:

  • avoids repetition
  • is resistant against typos when constructing an object
  • works well with subclassing (can just super().__init(...))
  • allows for documentation of the attributes on a class-level (where they belong) rather than in X.__init__

Prior to Python 3.6, this gives no control over the order in which the attributes are set, which could be a problem if some attributes are properties with setters that access other attributes.

It could probably be improved upon a bit, but I’m the only user of my own code so I am not worried about any form of input sanitation. Perhaps an AttributeError would be more appropriate.


回答 5

您也可以这样做:

locs = locals()
for arg in inspect.getargspec(self.__init__)[0][1:]:
    setattr(self, arg, locs[arg])

当然,您将必须导入inspect模块。

You could also do:

locs = locals()
for arg in inspect.getargspec(self.__init__)[0][1:]:
    setattr(self, arg, locs[arg])

Of course, you would have to import the inspect module.


回答 6

这是一个无需任何其他导入的解决方案。

辅助功能

一个小的辅助函数使它更加方便和可重复使用:

def auto_init(local_name_space):
    """Set instance attributes from arguments.
    """
    self = local_name_space.pop('self')
    for name, value in local_name_space.items():
        setattr(self, name, value)

应用

您需要使用以下命令调用它locals()

class A:
    def __init__(self, x, y, z):
        auto_init(locals())

测试

a = A(1, 2, 3)
print(a.__dict__)

输出:

{'y': 2, 'z': 3, 'x': 1}

不变 locals()

如果您不想更改,请locals()使用以下版本:

def auto_init(local_name_space):
    """Set instance attributes from arguments.
    """
    for name, value in local_name_space.items():
        if name != 'self': 
            setattr(local_name_space['self'], name, value)

This is a solution without any additional imports.

Helper function

A small helper function makes it more convenient and re-usable:

def auto_init(local_name_space):
    """Set instance attributes from arguments.
    """
    self = local_name_space.pop('self')
    for name, value in local_name_space.items():
        setattr(self, name, value)

Application

You need to call it with locals():

class A:
    def __init__(self, x, y, z):
        auto_init(locals())

Test

a = A(1, 2, 3)
print(a.__dict__)

Output:

{'y': 2, 'z': 3, 'x': 1}

Without changing locals()

If you don’t like to change locals() use this version:

def auto_init(local_name_space):
    """Set instance attributes from arguments.
    """
    for name, value in local_name_space.items():
        if name != 'self': 
            setattr(local_name_space['self'], name, value)

回答 7

一个有趣的库可以处理这个问题(并避免很多其他样板文件)是attrs。例如,您的示例可以简化为以下示例(假设该类称为MyClass):

import attr

@attr.s
class MyClass:
    x = attr.ib()
    y = attr.ib()
    z = attr.ib()

您甚至不需要任何__init__方法,除非它也执行其他操作。这是Glyph Lefkowitz的精彩介绍

An interesting library that handles this (and avoids a lot of other boilerplate) is attrs. Your example, for instance, could be reduced to this (assume the class is called MyClass):

import attr

@attr.s
class MyClass:
    x = attr.ib()
    y = attr.ib()
    z = attr.ib()

You don’t even need an __init__ method anymore, unless it does other stuff as well. Here’s a nice introduction by Glyph Lefkowitz.


回答 8

我的0.02 $。它与Joran Beasley的答案非常接近,但更为优雅:

def __init__(self, a, b, c, d, e, f):
    vars(self).update((k, v) for k, v in locals().items() if v is not self)

此外,可以使用以下技术来减少MikeMüller的答案(最适合我的口味):

def auto_init(ns):
    self = ns.pop('self')
    vars(self).update(ns)

auto_init(locals())您的来话__init__

My 0.02$. It is very close to Joran Beasley answer, but more elegant:

def __init__(self, a, b, c, d, e, f):
    vars(self).update((k, v) for k, v in locals().items() if v is not self)

Additionally, Mike Müller’s answer (the best one to my taste) can be reduced with this technique:

def auto_init(ns):
    self = ns.pop('self')
    vars(self).update(ns)

And the just call auto_init(locals()) from your __init__


回答 9

这是用Python做事的自然方法。不要尝试发明更聪明的东西,它会导致代码太聪明,而团队中没人会理解。如果您想成为团队合作者,然后继续以这种方式编写。

It’s a natural way to do things in Python. Don’t try to invent something more clever, it will lead to overly clever code that no one on your team will understand. If you want to be a team player and then keep writing it this way.


回答 10

Python 3.7以上

在Python 3.7中,您可以(ab)使用模块dataclass提供的装饰器dataclasses。从文档中:

该模块提供了一个装饰器和一些函数,用于自动将生成的特殊方法(例如__init__()和)添加__repr__()到用户定义的类中。它最初在PEP 557中进行了描述。

这些生成的方法中使用的成员变量是使用PEP 526类型注释定义的。例如此代码:

@dataclass
class InventoryItem:
    '''Class for keeping track of an item in inventory.'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

除其他外,将添加__init__()如下所示的:

def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0):
      self.name = name
      self.unit_price = unit_price
      self.quantity_on_hand = quantity_on_hand

请注意,此方法会自动添加到类中:上面显示的InventoryItem定义中未直接指定此方法。

如果您的类又大又复杂,那么使用可能是不合适的dataclass。我在Python 3.7.0发行之日就在写这篇文章,因此用法模式尚未很好地建立。

Python 3.7 onwards

In Python 3.7, you may (ab)use the dataclass decorator, available from the dataclasses module. From the documentation:

This module provides a decorator and functions for automatically adding generated special methods such as __init__() and __repr__() to user-defined classes. It was originally described in PEP 557.

The member variables to use in these generated methods are defined using PEP 526 type annotations. For example this code:

@dataclass
class InventoryItem:
    '''Class for keeping track of an item in inventory.'''
    name: str
    unit_price: float
    quantity_on_hand: int = 0

    def total_cost(self) -> float:
        return self.unit_price * self.quantity_on_hand

Will add, among other things, a __init__() that looks like:

def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0):
      self.name = name
      self.unit_price = unit_price
      self.quantity_on_hand = quantity_on_hand

Note that this method is automatically added to the class: it is not directly specified in the InventoryItem definition shown above.

If your class is large and complex, it may be inappropriate to use a dataclass. I’m writing this on the day of release of Python 3.7.0, so usage patterns are not yet well established.


为什么Python的math.ceil()和math.floor()操作返回浮点数而不是整数?

问题:为什么Python的math.ceil()和math.floor()操作返回浮点数而不是整数?

有人可以解释一下吗(直接来自文档 -我的重点):

math.ceil(x)以浮点数形式返回x的上限,最小数值大于或等于x。

math.floor(x)以浮点数形式返回x的下限,即小于或等于x 的最大数值。

为什么会.ceil.floor回报花车当它们被定义应该算整数?


编辑:

好吧,这有一些很好的论据来说明为什么它们应该返回浮点数,而当@jcollado指出它们实际上确实在Python 3中返回整数时,我才刚刚习惯这个想法。

Can someone explain this (straight from the docs– emphasis mine):

math.ceil(x) Return the ceiling of x as a float, the smallest integer value greater than or equal to x.

math.floor(x) Return the floor of x as a float, the largest integer value less than or equal to x.

Why would .ceil and .floor return floats when they are by definition supposed to calculate integers?


EDIT:

Well this got some very good arguments as to why they should return floats, and I was just getting used to the idea, when @jcollado pointed out that they in fact do return ints in Python 3…


回答 0

浮点数的范围通常超过整数的范围。通过返回浮点值,函数可以为超出可表示的整数范围的输入值返回有意义的值。

考虑:如果floor()返回整数,应该floor(1.0e30)返回什么?

现在,尽管Python的整数现在具有任意精度,但并不总是这样。标准库函数是等效C库函数的精简包装。

The range of floating point numbers usually exceeds the range of integers. By returning a floating point value, the functions can return a sensible value for input values that lie outside the representable range of integers.

Consider: If floor() returned an integer, what should floor(1.0e30) return?

Now, while Python’s integers are now arbitrary precision, it wasn’t always this way. The standard library functions are thin wrappers around the equivalent C library functions.


回答 1

正如其他答案所指出的那样,在python中,它们返回浮点数的原因可能是出于防止溢出问题的历史原因。但是,它们在python 3中返回整数。

>>> import math
>>> type(math.floor(3.1))
<class 'int'>
>>> type(math.ceil(3.1))
<class 'int'>

您可以在PEP 3141中找到更多信息。

As pointed out by other answers, in python they return floats probably because of historical reasons to prevent overflow problems. However, they return integers in python 3.

>>> import math
>>> type(math.floor(3.1))
<class 'int'>
>>> type(math.ceil(3.1))
<class 'int'>

You can find more information in PEP 3141.


回答 2

您的评论明显说明了您的困惑:

ceil / floor操作的重点是将浮点数转换为整数!

ceil和floor操作的重点是将浮点数据舍入为整数值。不做类型转换。需要获取数值的用户可以在操作之后进行显式转换。

请注意,如果所有可用的都是返回整数的ceil或float运算,则不可能简单地实现舍入到整数值。您需要首先检查输入是否在可表示的整数范围内,然后调用该函数;您将需要在单独的代码路径中处理NaN和无穷大。

此外,如果要符合IEEE 754,则必须具有返回浮点数的ceil和floor版本。

The source of your confusion is evident in your comment:

The whole point of ceil/floor operations is to convert floats to integers!

The point of the ceil and floor operations is to round floating-point data to integral values. Not to do a type conversion. Users who need to get integer values can do an explicit conversion following the operation.

Note that it would not be possible to implement a round to integral value as trivially if all you had available were a ceil or float operation that returned an integer. You would need to first check that the input is within the representable integer range, then call the function; you would need to handle NaN and infinities in a separate code path.

Additionally, you must have versions of ceil and floor which return floating-point numbers if you want to conform to IEEE 754.


回答 3

因为python的数学库是对返回浮点数的C数学库的精简包装。

Because python’s math library is a thin wrapper around the C math library which returns floats.


回答 4

在Python 2.4之前的版本中,整数不能容纳所有范围的截断实数。

http://docs.python.org/whatsnew/2.4.html#pep-237-unifying-long-integers-and-integers

Before Python 2.4, an integer couldn’t hold the full range of truncated real numbers.

http://docs.python.org/whatsnew/2.4.html#pep-237-unifying-long-integers-and-integers


回答 5

因为float的范围大于整数的范围-返回整数可能会溢出

Because the range for floats is greater than that of integers — returning an integer could overflow


回答 6

这是一个非常有趣的问题!因为浮点数需要一些位来存储指数(= bits_for_exponent),所以任何大于2**(float_size - bits_for_exponent)整数的浮点数始终是整数!在另一个极端与负指数的浮动会给之一10-1。这使整数范围浮点范围的讨论变得毫无意义,因为只要数字超出整数类型的范围,这些函数将简单地返回原始数字。python函数是函数的包装器,C因此这确实是C函数的不足之处,它们应该返回整数并强制程序员执行范围NaN//Inf在调用ceil / floor之前检查。

因此,逻辑上的答案是这些函数唯一有用的函数,它们将返回整数范围内的值,因此,它们返回浮点数的事实是一个错误,您非常聪明地意识到这一点!

This is a very interesting question! As a float requires some bits to store the exponent (=bits_for_exponent) any floating point number greater than 2**(float_size - bits_for_exponent) will always be an integral value! At the other extreme a float with a negative exponent will give one of 1, 0 or -1. This makes the discussion of integer range versus float range moot because these functions will simply return the original number whenever the number is outside the range of the integer type. The python functions are wrappers of the C function and so this is really a deficiency of the C functions where they should have returned an integer and forced the programer to do the range/NaN/Inf check before calling ceil/floor.

Thus the logical answer is the only time these functions are useful they would return a value within integer range and so the fact they return a float is a mistake and you are very smart for realizing this!


回答 7

也许因为其他语言也这样做,所以它是普遍接受的行为。(有充分的理由,如其他答案所示)

Maybe because other languages do this as well, so it is generally-accepted behavior. (For good reasons, as shown in the other answers)


Django DB设置“配置不正确”错误

问题:Django DB设置“配置不正确”错误

Django(1.5)对我来说很好用,但是当我启动Python解释器(Python 3)进行检查时,尝试导入时会遇到最奇怪的错误from django.contrib.auth.models import User

Traceback (most recent call last):
  File "/usr/local/lib/python3.2/dist-packages/django/conf/__init__.py", line 36, in _setup
    settings_module = os.environ[ENVIRONMENT_VARIABLE]
  File "/usr/lib/python3.2/os.py", line 450, in __getitem__
    value = self._data[self.encodekey(key)]
KeyError: b'DJANGO_SETTINGS_MODULE'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.2/dist-packages/django/contrib/auth/models.py", line 8, in <module>
    from django.db import models
  File "/usr/local/lib/python3.2/dist-packages/django/db/__init__.py", line 11, in <module>
    if settings.DATABASES and DEFAULT_DB_ALIAS not in settings.DATABASES:
  File "/usr/local/lib/python3.2/dist-packages/django/conf/__init__.py", line 52, in __getattr__
    self._setup(name)
  File "/usr/local/lib/python3.2/dist-packages/django/conf/__init__.py", line 45, in _setup
    % (desc, ENVIRONMENT_VARIABLE))

django.core.exceptions.ImproperlyConfigured: Requested setting DATABASES, 
  but settings are not configured. You must either define the environment 
  variable DJANGO_SETTINGS_MODULE or call settings.configure() 
  before accessing settings.

当它在Python解释器之外可以正常工作时,如何对其进行不正确的配置?在我的Django设置中,DATABASES设置为:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'django_db', # Or path to database file if using sqlite3.
        # The following settings are not used with sqlite3:
        'USER': 'zamphatta',
        'PASSWORD': 'mypassword91',
        'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
        'PORT': '', # Set to empty string for default.
    }
}

…这是如何配置不正确的?

Django (1.5) is workin’ fine for me, but when I fire up the Python interpreter (Python 3) to check some things, I get the weirdest error when I try importing – from django.contrib.auth.models import User

Traceback (most recent call last):
  File "/usr/local/lib/python3.2/dist-packages/django/conf/__init__.py", line 36, in _setup
    settings_module = os.environ[ENVIRONMENT_VARIABLE]
  File "/usr/lib/python3.2/os.py", line 450, in __getitem__
    value = self._data[self.encodekey(key)]
KeyError: b'DJANGO_SETTINGS_MODULE'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.2/dist-packages/django/contrib/auth/models.py", line 8, in <module>
    from django.db import models
  File "/usr/local/lib/python3.2/dist-packages/django/db/__init__.py", line 11, in <module>
    if settings.DATABASES and DEFAULT_DB_ALIAS not in settings.DATABASES:
  File "/usr/local/lib/python3.2/dist-packages/django/conf/__init__.py", line 52, in __getattr__
    self._setup(name)
  File "/usr/local/lib/python3.2/dist-packages/django/conf/__init__.py", line 45, in _setup
    % (desc, ENVIRONMENT_VARIABLE))

django.core.exceptions.ImproperlyConfigured: Requested setting DATABASES, 
  but settings are not configured. You must either define the environment 
  variable DJANGO_SETTINGS_MODULE or call settings.configure() 
  before accessing settings.

How could it be improperly configured, when it works fine outside the Python interpreter? In my Django settings, the DATABASES settings are:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'django_db', # Or path to database file if using sqlite3.
        # The following settings are not used with sqlite3:
        'USER': 'zamphatta',
        'PASSWORD': 'mypassword91',
        'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
        'PORT': '', # Set to empty string for default.
    }
}

…how is this improperly configured?


回答 0

您不能只启动Python并检查内容,Django不知道您要处理哪个项目。您必须执行以下操作之一:

  • python manage.py shell
  • 使用django-admin.py shell --settings=mysite.settings(或您使用的任何设置模块)
  • DJANGO_SETTINGS_MODULE操作系统中的环境变量设置为mysite.settings
  • (在Django 1.6中已删除)setup_environ在python解释器中使用:

    from django.core.management import setup_environ
    from mysite import settings
    
    setup_environ(settings)
    

自然,第一种方法是最简单的。

You can’t just fire up Python and check things, Django doesn’t know what project you want to work on. You have to do one of these things:

  • Use python manage.py shell
  • Use django-admin.py shell --settings=mysite.settings (or whatever settings module you use)
  • Set DJANGO_SETTINGS_MODULE environment variable in your OS to mysite.settings
  • (This is removed in Django 1.6) Use setup_environ in the python interpreter:

    from django.core.management import setup_environ
    from mysite import settings
    
    setup_environ(settings)
    

Naturally, the first way is the easiest.


回答 1

在您的python shell / ipython中执行以下操作:

from django.conf import settings

settings.configure()

In your python shell/ipython do:

from django.conf import settings

settings.configure()

回答 2

在2017年使用django 1.11.5和python 3.6(从注释中也可以使用python 2.7):

import django
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
django.setup()

.py其中你把这个代码应该是在mysite(父之一)

In 2017 with django 1.11.5 and python 3.6 (from the comment this also works with Python 2.7):

import django
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
django.setup()

The .py in which you put this code should be in mysite (the parent one)


回答 3

在Django 1.9上,我尝试django-admin runserver并得到了相同的错误,但是当我使用时python manage.py runserver,得到了预期的结果。这可能会解决很多人的这个错误!

On Django 1.9, I tried django-admin runserver and got the same error, but when I used python manage.py runserver I got the intended result. This may solve this error for a lot of people!


回答 4

就我而言,尝试通过PyCharm运行Django测试时遇到了这个问题。我认为这是因为PyCharm不会加载初始Django项目设置,即manage.py shell最初运行的设置。可以将它们添加到测试脚本的开头,也可以使用来运行测试manage.py test

版本:

  • Python 3.5(在virtualenv中)
  • PyCharm 2016.3.2专业版
  • Django 1.10

In my case, I got this when trying to run Django tests through PyCharm. I think it is because PyCharm does not load the initial Django project settings, i.e. those that manage.py shell runs initially. One can add them to the start of the testing script or just run the tests using manage.py test.

Versions:

  • Python 3.5 (in virtualenv)
  • PyCharm 2016.3.2 Professional
  • Django 1.10

回答 5

就我自己而言,在python2.7.11上运行的django 1.10.1中,我试图使用django-admin runserver而不是manage.py runserver在我的项目目录中启动服务器。

in my own case in django 1.10.1 running on python2.7.11, I was trying to start the server using django-admin runserver instead of manage.py runserver in my project directory.


回答 6

对于使用IntelliJ的人,通过这些设置,我可以从外壳程序(在Windows上)进行查询。

For people using IntelliJ, with these settings I was able to query from the shell (on windows).


使用IPython进行分步调试

问题:使用IPython进行分步调试

根据我的阅读,有两种方法可以在Python中调试代码:

  • 使用传统的调试器,例如pdbipdb。它支持诸如cfor continuenfor step-oversfor step-into等命令,但是您没有直接访问IPython shell的权限,这对于对象检查非常有用。

  • 通过 IPython shell 嵌入代码中来使用 IPython。您可以这样做,然后在您的代码中使用。当您的程序/脚本命中一条语句时,您将进入IPython shell。这允许使用所有IPython好东西对对象进行全面检查并测试Python代码。但是,在使用时,您将无法通过便捷的键盘快捷键逐步完成代码。from ipython import embedembed()embed()embed()

有什么办法可以融合两全其美?即

  1. 能够 使用方便的pdb / ipdb键盘快捷键逐步完成代码。
  2. 在任何这样的步骤(例如,在给定的语句上),都可以访问成熟的IPython shell

如在 MATLAB中一样进行 IPython调试:

在MATLAB中可以找到这种“增强调试”类型的示例,在该示例中,用户始终可以完全访问MATLAB引擎/外壳,并且她仍然可以逐步完成代码,定义条件断点等。我已经与其他用户讨论过,这是人们从MATLAB转移到IPython时最想念的调试功能。

在Emacs和其他编辑器中进行IPython调试:

我不想让这个问题过于具体,但是我主要在Emacs中工作,所以我想知道是否有任何方法可以将此功能引入其中。理想情况下,Emacs(或编辑器)将允许程序员在代码上的任意位置设置断点,并与解释器或调试器进行通信,以使其在您选择的位置停止,并在该位置提供完整的IPython解释器。

From what I have read, there are two ways to debug code in Python:

  • With a traditional debugger such as pdb or ipdb. This supports commands such as c for continue, n for step-over, s for step-into etc.), but you don’t have direct access to an IPython shell which can be extremely useful for object inspection.

  • Using IPython by embedding an IPython shell in your code. You can do from IPython import embed, and then use embed() in your code. When your program/script hits an embed() statement, you are dropped into an IPython shell. This allows the full inspection of objects and testing of Python code using all the IPython goodies. However, when using embed() you can’t step-by-step through the code anymore with handy keyboard shortcuts.

Is there any way to combine the best of both worlds? I.e.

  1. Be able to step-by-step through your code with handy pdb/ipdb keyboard shortcuts.
  2. At any such step (e.g. on a given statement), have access to a full-fledged IPython shell.

IPython debugging as in MATLAB:

An example of this type of “enhanced debugging” can be found in MATLAB, where the user always has full access to the MATLAB engine/shell, and she can still step-by-step through her code, define conditional breakpoints, etc. From what I have discussed with other users, this is the debugging feature that people miss the most when moving from MATLAB to IPython.

IPython debugging in Emacs and other editors:

I don’t want to make the question too specific, but I work mostly in Emacs, so I wonder if there is any way to bring this functionality into it. Ideally, Emacs (or the editor) would allow the programmer to set breakpoints anywhere on the code and communicate with the interpreter or debugger to have it stop in the location of your choice, and bring to a full IPython interpreter on that location.


回答 0

您可以使用IPython的%pdb魔力。只需调用%pdbIPython,当发生错误时,您会自动转到ipdb。虽然您没有立即迈出一步,但您ipdb之后就进入了。

这使调试单个函数变得容易,因为您可以使用加载文件%load然后运行一个函数。您可以assert在正确的位置使用来强制执行错误。

%pdb是线魔术。呼之为%pdb on%pdb 1%pdb off%pdb 0。如果在不带参数的情况下调用它,则它将作为切换。

You can use IPython’s %pdb magic. Just call %pdb in IPython and when an error occurs, you’re automatically dropped to ipdb. While you don’t have the stepping immediately, you’re in ipdb afterwards.

This makes debugging individual functions easy, as you can just load a file with %load and then run a function. You could force an error with an assert at the right position.

%pdb is a line magic. Call it as %pdb on, %pdb 1, %pdb off or %pdb 0. If called without argument it works as a toggle.


回答 1

ipdb.set_trace()呢?在您的代码中:

import ipdb; ipdb.set_trace()

更新:现在在Python 3.7中,我们可以编写breakpoint()。它的工作原理相同,但也遵守PYTHONBREAKPOINT环境变量。此功能来自此PEP

这样可以对代码进行全面检查,并且您可以访问诸如c(继续),n(执行下一行),s(进入当前方法)之类的命令。

请参阅ipdb repo命令列表IPython现在称为Jupyter(的一部分)。


ps:请注意,ipdb命令优先于python代码。所以为了写,list(foo)你需要print list(foo)

另外,如果您喜欢ipython提示符(它的emacs和vim模式,历史记录,完成情况等),由于它基于python提示符工具包,因此很容易为您的项目获得相同的名称。

What about ipdb.set_trace() ? In your code :

import ipdb; ipdb.set_trace()

update: now in Python 3.7, we can write breakpoint(). It works the same, but it also obeys to the PYTHONBREAKPOINT environment variable. This feature comes from this PEP.

This allows for full inspection of your code, and you have access to commands such as c (continue), n (execute next line), s (step into the method at point) and so on.

See the ipdb repo and a list of commands. IPython is now called (edit: part of) Jupyter.


ps: note that an ipdb command takes precedence over python code. So in order to write list(foo) you’d need print(list(foo)), or !list(foo) .

Also, if you like the ipython prompt (its emacs and vim modes, history, completions,…) it’s easy to get the same for your project since it’s based on the python prompt toolkit.


回答 2

(2016年5月28日更新)在Emacs中使用RealGUD

对于Emacs中的任何人,此线程都说明了如何使用

  1. Emacs中一个称为RealGUD的新的重要调试器,可以与任何调试器(包括ipdb)一起使用。
  2. Emacs软件包isend-mode

这两个软件包的组合非常强大,可以使它们完全重新创建OP中描述的行为,甚至可以做更多的事情。

有关RealGUD for ipdb 的Wiki文章的更多信息。


原始答案:

在尝试了多种不同的调试Python方法(包括本线程中提到的所有内容)之后,我使用IPython调试Python的首选方法之一是使用嵌入式外壳程序。

定义定制的嵌入式IPython Shell:

将以下内容添加到脚本中PYTHONPATH,以使该方法ipsh()可用。

import inspect

# First import the embed function
from IPython.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config

# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = '   .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '

# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")   
exit_msg = '**Leaving Nested interpreter'

# Wrap it in a function that gives me more context:
def ipsh():
    ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)

    frame = inspect.currentframe().f_back
    msg   = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)

    # Go back one level! 
    # This is needed because the call to ipshell is inside the function ipsh()
    ipshell(msg,stack_depth=2)

然后,每当我要调试代码中的某些内容时,就将其放置ipsh()在需要进行对象检查等的位置。例如,说我要在my_function下面调试

使用它:

def my_function(b):
  a = b
  ipsh() # <- This will embed a full-fledged IPython interpreter
  a = 4

然后my_function(2)以下列方式之一调用:

  1. 通过运行从Unix Shell调用此函数的Python程序
  2. 或直接从IPython调用

不管我如何调用它,解释器都会停在所说的行ipsh()。完成后,您可以执行操作Ctrl-D,Python将恢复执行(使用您所做的任何变量更新)。请注意,如果您从常规IPython IPython Shell(上面的案例2)运行代码,那么新的IPython Shell将嵌套在您从中调用它的外壳内,这很好,但是请注意。无论哪种方式,一旦解释器停在的位置ipsh,我都可以检查a2)的值,查看定义了哪些函数和对象,等等。

问题:

上面的解决方案可以使Python在代码中所需的任何位置停止,然后将您带入完整的IPython解释器。不幸的是,调用脚本后,它不允许您添加或删除断点,这非常令人沮丧。在我看来,这是阻止IPython成为Python出色的调试工具的唯一原因

您目前可以做的最好的事情是:

一种解决方法是ipsh()在要Python解释程序启动IPython Shell的不同位置(即breakpoint)放置先验先验。然后,您可以使用以下命令在不同的预定义,硬编码的“断点”之间“跳转”Ctrl-D,这将退出当前的嵌入式IPython shell,并且每当解释器单击下一个调用时再次停止ipsh()

如果走这条路线,退出“调试模式”并忽略所有后续断点的一种方法是使用ipshell.dummy_mode = True,这将使Python忽略ipshell我们在上面创建的对象的任何后续实例化。

(Update on May 28, 2016) Using RealGUD in Emacs

For anyone in Emacs, this thread shows how to accomplish everything described in the OP (and more) using

  1. a new important debugger in Emacs called RealGUD which can operate with any debugger (including ipdb).
  2. The Emacs package isend-mode.

The combination of these two packages is extremely powerful and allows one to recreate exactly the behavior described in the OP and do even more.

More info on the wiki article of RealGUD for ipdb.


Original answer:

After having tried many different methods for debugging Python, including everything mentioned in this thread, one of my preferred ways of debugging Python with IPython is with embedded shells.

Defining a custom embedded IPython shell:

Add the following on a script to your PYTHONPATH, so that the method ipsh() becomes available.

import inspect

# First import the embed function
from IPython.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config

# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = '   .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '

# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")   
exit_msg = '**Leaving Nested interpreter'

# Wrap it in a function that gives me more context:
def ipsh():
    ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)

    frame = inspect.currentframe().f_back
    msg   = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)

    # Go back one level! 
    # This is needed because the call to ipshell is inside the function ipsh()
    ipshell(msg,stack_depth=2)

Then, whenever I want to debug something in my code, I place ipsh() right at the location where I need to do object inspection, etc. For example, say I want to debug my_function below

Using it:

def my_function(b):
  a = b
  ipsh() # <- This will embed a full-fledged IPython interpreter
  a = 4

and then I invoke my_function(2) in one of the following ways:

  1. Either by running a Python program that invokes this function from a Unix shell
  2. Or by invoking it directly from IPython

Regardless of how I invoke it, the interpreter stops at the line that says ipsh(). Once you are done, you can do Ctrl-D and Python will resume execution (with any variable updates that you made). Note that, if you run the code from a regular IPython the IPython shell (case 2 above), the new IPython shell will be nested inside the one from which you invoked it, which is perfectly fine, but it’s good to be aware of. Eitherway, once the interpreter stops on the location of ipsh, I can inspect the value of a (which be 2), see what functions and objects are defined, etc.

The problem:

The solution above can be used to have Python stop anywhere you want in your code, and then drop you into a fully-fledged IPython interpreter. Unfortunately it does not let you add or remove breakpoints once you invoke the script, which is highly frustrating. In my opinion, this is the only thing that is preventing IPython from becoming a great debugging tool for Python.

The best you can do for now:

A workaround is to place ipsh() a priori at the different locations where you want the Python interpreter to launch an IPython shell (i.e. a breakpoint). You can then “jump” between different pre-defined, hard-coded “breakpoints” with Ctrl-D, which would exit the current embedded IPython shell and stop again whenever the interpreter hits the next call to ipsh().

If you go this route, one way to exit “debugging mode” and ignore all subsequent breakpoints, is to use ipshell.dummy_mode = True which will make Python ignore any subsequent instantiations of the ipshell object that we created above.


回答 3

您可以从pudb启动IPython会话,然后根据需要返回调试会话。

顺便说一句,ipdb在幕后使用IPython,您实际上可以使用IPython功能,例如TAB完成和魔术命令(以开头的命令%)。如果你是IPDB OK,你可以从IPython中使用命令,如启动%run%debug。从某种意义上讲,ipdb会话实际上比普通的IPython会话要好,因为您可以在堆栈跟踪中上下移动。ipdb中“对象检查”缺少什么?

另外,与Emacs> = 24.3捆绑在一起的python.el具有不错的ipdb支持。

You can start IPython session from pudb and go back to the debugging session as you like.

BTW, ipdb is using IPython behind the scenes and you can actually use IPython functionality such as TAB completion and magic commands (the one starts with %). If you are OK with ipdb you can start it from IPython using commands such as %run and %debug. ipdb session is actually better than plain IPython one in the sense you can go up and down in the stack trace etc. What is missing in ipdb for “object inspection”?

Also, python.el bundled with Emacs >= 24.3 has nice ipdb support.


回答 4

似乎@gaborous的答案中的方法已被弃用

新方法似乎是:

from IPython.core import debugger
debug = debugger.Pdb().set_trace

def buggy_method():
    debug()

Looks like the approach in @gaborous’s answer is deprecated.

The new approach seems to be:

from IPython.core import debugger
debug = debugger.Pdb().set_trace

def buggy_method():
    debug()

回答 5

前缀“!” 在pdb中键入命令的符号似乎与在IPython shell中执行操作具有相同的效果。这适用于访问某些功能甚至变量名的帮助。也许这会对您有所帮助。例如,

ipdb> help(numpy.transpose)
*** No help on (numpy.transpose)

但是!help(numpy.transpose)将为您提供有关numpy.transpose的预期帮助页面。同样,对于变量名,假设您有一个变量l,在pdb中键入“ l”会列出代码,但是!l会打印出l的值。

Prefixing an “!” symbol to commands you type in pdb seems to have the same effect as doing something in an IPython shell. This works for accessing help for a certain function, or even variable names. Maybe this will help you to some extent. For example,

ipdb> help(numpy.transpose)
*** No help on (numpy.transpose)

But !help(numpy.transpose) will give you the expected help page on numpy.transpose. Similarly for variable names, say you have a variable l, typing “l” in pdb lists the code, but !l prints the value of l.


回答 6

您是否尝试过此技巧

或者更好的是,使用ipython并调用:

from IPython.Debugger import Tracer; debug_here = Tracer()

那你就可以用

debug_here()

每当你想设置一个断点

Did you try this tip?

Or better still, use ipython, and call:

from IPython.Debugger import Tracer; debug_here = Tracer()

then you can just use

debug_here()

whenever you want to set a breakpoint


回答 7

您可以IPython 从内部 开始ipdb

引入ipdb调试器1

import idpb; ipdb.set_trace()

输入IPython的从内部ipdb>控制台2

from IPython import embed; embed()

ipdb>从以下位置返回到控制台IPython

exit

如果您有幸使用Emacs,可以使事情变得更加便捷!

这需要使用M-x shell。使用yasnippetbm,定义以下代码段。这将用行替换ipdb编辑器中的文本set-trace。插入代码段后,该行将突出显示,以便易于观察和导航。使用M-x bm-next导航。

# -*- mode: snippet -*-
# name: ipdb
# key: ipdb
# expand-env: ((yas-after-exit-snippet-hook #'bm-toggle))
# --
import ipdb; ipdb.set_trace()

1全部一行,易于删除。由于imports仅发生一次,因此此表单确保ipdb将在您需要时将其导入,而不会产生额外的开销。

2,您可以通过导入自己节省一些打字IPython 的内.pdbrc文件

try:
    from IPython import embed
except:
    pass

这使您可以简单地embed()从内部进行调用ipdb(当然,仅在安装IPython时)。

You can start IPython from within ipdb!

Induce the ipdb debugger1:

import idpb; ipdb.set_trace()

Enter IPython from within in the ipdb> console2:

from IPython import embed; embed()

Return to the ipdb> console from within IPython:

exit

If you’re lucky enough to be using Emacs, things can be made even more convenient!

This requires using M-x shell. Using yasnippet and bm, define the following snippet. This will replace the text ipdb in the editor with the set-trace line. After inserting the snippet, the line will be highlighted so that it is easily noticeable and navigable. Use M-x bm-next to navigate.

# -*- mode: snippet -*-
# name: ipdb
# key: ipdb
# expand-env: ((yas-after-exit-snippet-hook #'bm-toggle))
# --
import ipdb; ipdb.set_trace()

1 All on one line for easy deletion. Since imports only happen once, this form ensures ipdb will be imported when you need it with no extra overhead.

2 You can save yourself some typing by importing IPython within your .pdbrc file:

try:
    from IPython import embed
except:
    pass

This allows you to simply call embed() from within ipdb (of course, only when IPython is installed).


回答 8

一种选择是使用像Spyder这样的IDE ,它应该允许您在调试时与代码进行交互(实际上是使用IPython控制台)。实际上,Spyder非常类似于MATLAB,我认为这是故意的。其中包括变量检查器,变量编辑,对文档的内置访问等。

One option is to use an IDE like Spyder which should allow you to interact with your code while debugging (using an IPython console, in fact). In fact, Spyder is very MATLAB-like, which I presume was intentional. That includes variable inspectors, variable editing, built-in access to documentation, etc.


回答 9

该问题的正确,简单,酷爽的准确答案是将%run宏与-d标志一起使用。

In [4]: run -d myscript.py
NOTE: Enter 'c' at the ipdb>  prompt to continue execution.        
> /cygdrive/c/Users/mycodefolder/myscript.py(4)<module>()
      2                                                            
      3                        
----> 4 a=1                                            
      5 b=2

the right, easy, cool, exact answer for the question is to use %run macro with -d flag.

In [4]: run -d myscript.py
NOTE: Enter 'c' at the ipdb>  prompt to continue execution.        
> /cygdrive/c/Users/mycodefolder/myscript.py(4)<module>()
      2                                                            
      3                        
----> 4 a=1                                            
      5 b=2

回答 10

如果在embed()控制台中键入exit(),代码将继续并转到下一个embed()行。

If you type exit() in embed() console the code continue and go to the next embed() line.


回答 11

Pyzo IDE具有与OP问类似的功能。您不必以调试模式启动。与MATLAB相似,命令在shell中执行。在某些源代码行中设置断点时,IDE会在此处停止执行,并且您还可以调试和发出常规IPython命令。

但是,除非您设置了另一个断点,否则似乎单步执行(还好吗?)效果不佳(即在一行中停下来,然后步入另一功能)。

仍然来自MATLAB,这似乎是我找到的最佳解决方案。

The Pyzo IDE has similar capabilities as the OP asked for. You don’t have to start in debug mode. Similarly to MATLAB, the commands are executed in the shell. When you set up a break-point in some source code line, the IDE stops the execution there and you can debug and issue regular IPython commands as well.

It does seem however that step-into doesn’t (yet?) work well (i.e. stopping in one line and then stepping into another function) unless you set up another break-point.

Still, coming from MATLAB, this seems the best solution I’ve found.


回答 12

在python 3.2中,您具有interact命令,该命令可让您访问完整的python / ipython命令空间。

From python 3.2, you have the interact command, which gives you access to the full python/ipython command space.


回答 13

从Emacs的IPython-shell和通过pdb.set_trace()设置的断点运行应该可以。

与python-mode.el,Mx ipython RET等一起检查

Running from inside Emacs’ IPython-shell and breakpoint set via pdb.set_trace() should work.

Checked with python-mode.el, M-x ipython RET etc.


回答 14

开发新代码

在IPython中进行调试

  1. 使用Jupyter / IPython单元执行来加速实验迭代
  2. 使用%% debug逐步

单元格示例:

%%debug
...: for n in range(4):
...:    n>2

调试现有代码

IPython内部调试

  1. 调试损坏的单元测试: pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
  2. 调试测试箱子外面:breakpoint()python -m ipdb,等。
  3. IPython.embed()用于在调试器中需要时具有完整的IPython功能

关于Python的想法

我同意OP的观点,MATLAB可以很好地完成许多事情,Python仍然没有,而且确实应该这样做,因为该语言中的几乎所有内容都偏重于开发速度而不是生产速度。也许有一天,我将为CPython贡献一些琐碎的错误修复。

https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68

另请参见是否可以通过调试在IPython中运行命令?

Developing New Code

Debugging inside IPython

  1. Use Jupyter/IPython cell execution to speed up experiment iterations
  2. Use %%debug for step through

Cell Example:

%%debug
...: for n in range(4):
...:    n>2

Debugging Existing Code

IPython inside debugging

  1. Debugging a broken unit test: pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
  2. Debugging outside of test case: breakpoint(), python -m ipdb, etc.
  3. IPython.embed() for full IPython functionality where needed while in the debugger

Thoughts on Python

I agree with the OP that many things MATLAB does nicely Python still does not have and really should since just about everything in the language favors development speed over production speed. Maybe someday I will contribute more than trivial bug fixes to CPython.

https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68

See also Is it possible to run commands in IPython with debugging?


如何在Django中设置时区?

问题:如何在Django中设置时区?

在我的django项目的settings.py文件中,我有这行:

TIME_ZONE = 'UTC'

但是我希望我的应用程序在UTC + 2时区运行,所以我将其更改为

TIME_ZONE = 'UTC+2'

它给出了错误ValueError: Incorrect timezone setting: UTC+2。正确的做法是什么?

谢谢!

In my django project’s settings.py file, I have this line :

TIME_ZONE = 'UTC'

But I want my app to run in UTC+2 timezone, so I changed it to

TIME_ZONE = 'UTC+2'

It gives the error ValueError: Incorrect timezone setting: UTC+2. What is the correct way of doing this?

Thanks!


回答 0

以下是有效时区的列表:

http://en.wikipedia.org/wiki/List_of_tz_database_time_zones

您可以使用

TIME_ZONE = 'Europe/Istanbul'

适用于UTC + 02:00

Here is the list of valid timezones:

http://en.wikipedia.org/wiki/List_of_tz_database_time_zones

You can use

TIME_ZONE = 'Europe/Istanbul'

for UTC+02:00


回答 1

要从tz数据库获取一组所有有效的时区名称(id),可以在Python中使用pytzmodule

>>> import pytz # $ pip install pytz
>>> pytz.all_timezones_set
LazySet({'Africa/Abidjan',
         'Africa/Accra',
         'Africa/Addis_Ababa',
         'Africa/Algiers',
         'Africa/Asmara',
         'Africa/Asmera',
         ...
         'UTC',
         'Universal',
         'W-SU',
         'WET',
         'Zulu'})

To get a set of all valid timezone names (ids) from the tz database, you could use pytz module in Python:

>>> import pytz # $ pip install pytz
>>> pytz.all_timezones_set
LazySet({'Africa/Abidjan',
         'Africa/Accra',
         'Africa/Addis_Ababa',
         'Africa/Algiers',
         'Africa/Asmara',
         'Africa/Asmera',
         ...
         'UTC',
         'Universal',
         'W-SU',
         'WET',
         'Zulu'})

回答 2

tzinfo数据库中选择一个有效的时区。他们往往采取的形式如Africa/GaborneUS/Eastern

找到一个与您最近的城市相匹配的城市,或者一个与您的时区相匹配的城市,然后将您的值设置TIME_ZONE为match。

Choose a valid timezone from the tzinfo database. They tend to take the form e.g. Africa/Gaborne and US/Eastern

Find the one which matches the city nearest you, or the one which has your timezone, then set your value of TIME_ZONE to match.


回答 3

有效的timeZone值基于Linux和其他Unix系统使用的tz(时区)数据库。值是形式为“ Area / Location ”的字符串(xsd:string),其中:

区域是大陆或海洋的名称。当前区域包括:

  • 非洲
  • 美国(北美和南美)
  • 南极洲
  • 北极
  • 亚洲
  • 大西洋
  • 澳大利亚
  • 欧洲
  • Etc(行政区域。例如,“ Etc / UTC”代表协调世界时。)
  • 印第安人
  • 太平洋地区

位置是城市,岛屿或其他区域名称。

区域名称和输出缩写遵循POSIX(便携式操作系统接口)UNIX约定,该约定使用格林威治以西的正号(+)和格林威治以东的负号(-),这与通常预期的相反。例如,“ Etc / GMT + 4”对应于UTC(格林威治以西)之后4小时,而不是UTC(格林尼治东部)协调世界时之前4小时。

这是所有有效时区的列表

您可以按以下方式在settings.py中更改时区

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Kolkata'

USE_I18N = True

USE_L10N = True

USE_TZ = True

Valid timeZone values are based on the tz (timezone) database used by Linux and other Unix systems. The values are strings (xsd:string) in the form “Area/Location,” in which:

Area is a continent or ocean name. Area currently includes:

  • Africa
  • America (both North America and South America)
  • Antarctica
  • Arctic
  • Asia
  • Atlantic
  • Australia
  • Europe
  • Etc (administrative zone. For example, “Etc/UTC” represents Coordinated Universal Time.)
  • Indian
  • Pacific

Location is the city, island, or other regional name.

The zone names and output abbreviations adhere to POSIX (portable operating system interface) UNIX conventions, which uses positive (+) signs west of Greenwich and negative (-) signs east of Greenwich, which is the opposite of what is generally expected. For example, “Etc/GMT+4” corresponds to 4 hours behind UTC (that is, west of Greenwich) rather than 4 hours ahead of UTC (Coordinated Universal Time) (east of Greenwich).

Here is a list all valid timezones

You can change time zone in your settings.py as follows

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'Asia/Kolkata'

USE_I18N = True

USE_L10N = True

USE_TZ = True

回答 4

我发现了这个问题,希望将Django项目settings.py文件中的时区更改为英国。

在jfs解决方案中使用tz数据库,我找到了答案:

    TIME_ZONE = 'Europe/London'

I found this question looking to change the timezone in my Django project’s settings.py file to the United Kingdom.

Using the tz database in jfs’ solution I found the answer:

    TIME_ZONE = 'Europe/London'

回答 5

  1. 将TIME_ZONE更改为您的本地时区,并在“ setting.py”中将USE_TZ保持为True:

    TIME_ZONE =’亚洲/上海’

    USE_I18N =真

    USE_L10N =真

    USE_TZ =真

  2. 这会将datetime对象作为UTC写入并存储到后端数据库。

  3. 然后,使用template标记将前端模板中的UTC时间转换为:

                <td> 
                    {% load tz %}
                    {% get_current_timezone as tz %}
                    {% timezone tz %}
                        {{ message.log_date | time:'H:i:s' }}
                    {% endtimezone %} 
                </td>

或简洁地使用模板过滤器

                <td> 
                    {% load tz %}
                    {{ message.log_date | localtime | time:'H:i:s' }}
                </td>
  1. 您可以在官方文档中查看更多详细信息:默认时区和当前时区

    启用时区支持后,Django将日期时间信息存储在数据库中的UTC中,在内部使用可识别时区的日期时间对象,并将其以模板和形式转换为最终用户的时区。

  1. Change the TIME_ZONE to your local time zone, and keep USE_TZ as True in ‘setting.py’:

    TIME_ZONE = ‘Asia/Shanghai’

    USE_I18N = True

    USE_L10N = True

    USE_TZ = True

  2. This will write and store the datetime object as UTC to the backend database.

  3. Then use template tag to convert the UTC time in your frontend template as such:

                <td> 
                    {% load tz %}
                    {% get_current_timezone as tz %}
                    {% timezone tz %}
                        {{ message.log_date | time:'H:i:s' }}
                    {% endtimezone %} 
                </td>
    

or use the template filters concisely:

                <td> 
                    {% load tz %}
                    {{ message.log_date | localtime | time:'H:i:s' }}
                </td>
  1. You could check more details in the official doc: Default time zone and current time zone

    When support for time zones is enabled, Django stores datetime information in UTC in the database, uses time-zone-aware datetime objects internally, and translates them to the end user’s time zone in templates and forms.


回答 6

通用解决方案,基于Django的TZ名称支持:

UTC-2 = 'Etc/GMT+2'
UTC-1 = 'Etc/GMT+1'
UTC = 'Etc/GMT+0'
UTC+1 = 'Etc/GMT-1'
UTC+2 = 'Etc/GMT-2'

+/-特意切换。

Universal solution, based on Django’s TZ name support:

UTC-2 = 'Etc/GMT+2'
UTC-1 = 'Etc/GMT+1'
UTC = 'Etc/GMT+0'
UTC+1 = 'Etc/GMT-1'
UTC+2 = 'Etc/GMT-2'

+/- is intentionally switched.


回答 7

  1. 从以下位置下载最新的pytz文件(pytz-2019.3.tar.gz):

    https://pypi.org/simple/pytz/
  2. 复制并将其解压缩到您site_packages项目的目录中

  3. 在cmd中,转到解压缩的文件夹并运行:

    python setup.py install
  4. TIME_ZONE = 'Etc/GMT+2' 或国家名称

  1. download latest pytz file (pytz-2019.3.tar.gz) from:

    https://pypi.org/simple/pytz/
    
  2. copy and extract it to site_packages directory on yor project

  3. in cmd go to the extracted folder and run:

    python setup.py install
    
  4. TIME_ZONE = 'Etc/GMT+2' or country name


请求-如何判断您是否收到404

问题:请求-如何判断您是否收到404

我正在使用请求库并通过以下代码访问网站以从中收集数据:

r = requests.get(url)

我想为输入不正确的URL并返回404错误时添加错误测试。如果我有意输入无效的URL,请执行以下操作:

print r

我得到这个:

<Response [404]>

编辑:

我想知道如何测试。对象类型仍然相同。当我执行r.content或时r.text,我仅获得自定义404页面的HTML。

I’m using the Requests library and accessing a website to gather data from it with the following code:

r = requests.get(url)

I want to add error testing for when an improper URL is entered and a 404 error is returned. If I intentionally enter an invalid URL, when I do this:

print r

I get this:

<Response [404]>

EDIT:

I want to know how to test for that. The object type is still the same. When I do r.content or r.text, I simply get the HTML of a custom 404 page.


回答 0

看一下r.status_code属性

if r.status_code == 404:
    # A 404 was issued.

演示:

>>> import requests
>>> r = requests.get('http://httpbin.org/status/404')
>>> r.status_code
404

如果要requests引发错误代码(4xx或5xx)的异常,请调用r.raise_for_status()

>>> r = requests.get('http://httpbin.org/status/404')
>>> r.raise_for_status()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "requests/models.py", line 664, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error: NOT FOUND
>>> r = requests.get('http://httpbin.org/status/200')
>>> r.raise_for_status()
>>> # no exception raised.

您还可以在布尔上下文中测试响应对象。如果状态代码不是错误代码(4xx或5xx),则将其视为“ true”:

if r:
    # successful response

如果要更明确,请使用if r.ok:

Look at the r.status_code attribute:

if r.status_code == 404:
    # A 404 was issued.

Demo:

>>> import requests
>>> r = requests.get('http://httpbin.org/status/404')
>>> r.status_code
404

If you want requests to raise an exception for error codes (4xx or 5xx), call r.raise_for_status():

>>> r = requests.get('http://httpbin.org/status/404')
>>> r.raise_for_status()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "requests/models.py", line 664, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error: NOT FOUND
>>> r = requests.get('http://httpbin.org/status/200')
>>> r.raise_for_status()
>>> # no exception raised.

You can also test the response object in a boolean context; if the status code is not an error code (4xx or 5xx), it is considered ‘true’:

if r:
    # successful response

If you want to be more explicit, use if r.ok:.


使用Matplotlib绘制2D热图

问题:使用Matplotlib绘制2D热图

我想使用Matplotlib绘制2D热图。我的数据是一个n×n的Numpy数组,每个数组的值都在0到1之间。因此,对于该数组的(i,j)元素,我想在我的(i,j)坐标上绘制一个正方形热图,其颜色与数组中元素的值成比例。

我怎样才能做到这一点?

Using Matplotlib, I want to plot a 2D heat map. My data is an n-by-n Numpy array, each with a value between 0 and 1. So for the (i, j) element of this array, I want to plot a square at the (i, j) coordinate in my heat map, whose color is proportional to the element’s value in the array.

How can I do this?


回答 0

imshow()函数带有参数interpolation='nearest'cmap='hot'应该执行您想要的操作。

import matplotlib.pyplot as plt
import numpy as np

a = np.random.random((16, 16))
plt.imshow(a, cmap='hot', interpolation='nearest')
plt.show()

The imshow() function with parameters interpolation='nearest' and cmap='hot' should do what you want.

import matplotlib.pyplot as plt
import numpy as np

a = np.random.random((16, 16))
plt.imshow(a, cmap='hot', interpolation='nearest')
plt.show()


回答 1

Seaborn负责许多手动工作,并自动在图表的侧面绘制渐变等。

import numpy as np
import seaborn as sns
import matplotlib.pylab as plt

uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, linewidth=0.5)
plt.show()

或者,您甚至可以绘制正方形矩阵的上/下左/右三角形,例如,一个正方形且对称的相关矩阵,因此绘制所有值无论如何都是多余的。

corr = np.corrcoef(np.random.randn(10, 200))
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
    ax = sns.heatmap(corr, mask=mask, vmax=.3, square=True,  cmap="YlGnBu")
    plt.show()

Seaborn takes care of a lot of the manual work and automatically plots a gradient at the side of the chart etc.

import numpy as np
import seaborn as sns
import matplotlib.pylab as plt

uniform_data = np.random.rand(10, 12)
ax = sns.heatmap(uniform_data, linewidth=0.5)
plt.show()

Or, you can even plot upper / lower left / right triangles of square matrices, for example a correlation matrix which is square and is symmetric, so plotting all values would be redundant anyway.

corr = np.corrcoef(np.random.randn(10, 200))
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
with sns.axes_style("white"):
    ax = sns.heatmap(corr, mask=mask, vmax=.3, square=True,  cmap="YlGnBu")
    plt.show()


回答 2

对于二维numpy数组,简单地使用imshow()可能会帮助您:

import matplotlib.pyplot as plt
import numpy as np


def heatmap2d(arr: np.ndarray):
    plt.imshow(arr, cmap='viridis')
    plt.colorbar()
    plt.show()


test_array = np.arange(100 * 100).reshape(100, 100)
heatmap2d(test_array)

此代码产生连续的热图。

您可以colormap这里选择另一个内置的。

For a 2d numpy array, simply use imshow() may help you:

import matplotlib.pyplot as plt
import numpy as np


def heatmap2d(arr: np.ndarray):
    plt.imshow(arr, cmap='viridis')
    plt.colorbar()
    plt.show()


test_array = np.arange(100 * 100).reshape(100, 100)
heatmap2d(test_array)

This code produces a continuous heatmap.

You can choose another built-in colormap from here.


回答 3

我会使用matplotlib的pcolor / pcolormesh函数,因为它允许数据间距不均匀。

取自matplotlib的示例:

import matplotlib.pyplot as plt
import numpy as np

# generate 2 2d grids for the x & y bounds
y, x = np.meshgrid(np.linspace(-3, 3, 100), np.linspace(-3, 3, 100))

z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()

fig, ax = plt.subplots()

c = ax.pcolormesh(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
ax.set_title('pcolormesh')
# set the limits of the plot to the limits of the data
ax.axis([x.min(), x.max(), y.min(), y.max()])
fig.colorbar(c, ax=ax)

plt.show()

I would use matplotlib’s pcolor/pcolormesh function since it allows nonuniform spacing of the data.

Example taken from matplotlib:

import matplotlib.pyplot as plt
import numpy as np

# generate 2 2d grids for the x & y bounds
y, x = np.meshgrid(np.linspace(-3, 3, 100), np.linspace(-3, 3, 100))

z = (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)
# x and y are bounds, so z should be the value *inside* those bounds.
# Therefore, remove the last value from the z array.
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()

fig, ax = plt.subplots()

c = ax.pcolormesh(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
ax.set_title('pcolormesh')
# set the limits of the plot to the limits of the data
ax.axis([x.min(), x.max(), y.min(), y.max()])
fig.colorbar(c, ax=ax)

plt.show()


回答 4

这是从csv执行操作的方法:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

# Load data from CSV
dat = np.genfromtxt('dat.xyz', delimiter=' ',skip_header=0)
X_dat = dat[:,0]
Y_dat = dat[:,1]
Z_dat = dat[:,2]

# Convert from pandas dataframes to numpy arrays
X, Y, Z, = np.array([]), np.array([]), np.array([])
for i in range(len(X_dat)):
        X = np.append(X, X_dat[i])
        Y = np.append(Y, Y_dat[i])
        Z = np.append(Z, Z_dat[i])

# create x-y points to be used in heatmap
xi = np.linspace(X.min(), X.max(), 1000)
yi = np.linspace(Y.min(), Y.max(), 1000)

# Z is a matrix of x-y values
zi = griddata((X, Y), Z, (xi[None,:], yi[:,None]), method='cubic')

# I control the range of my colorbar by removing data 
# outside of my range of interest
zmin = 3
zmax = 12
zi[(zi<zmin) | (zi>zmax)] = None

# Create the contour plot
CS = plt.contourf(xi, yi, zi, 15, cmap=plt.cm.rainbow,
                  vmax=zmax, vmin=zmin)
plt.colorbar()  
plt.show()

dat.xyz形式在哪里

x1 y1 z1
x2 y2 z2
...

Here’s how to do it from a csv:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata

# Load data from CSV
dat = np.genfromtxt('dat.xyz', delimiter=' ',skip_header=0)
X_dat = dat[:,0]
Y_dat = dat[:,1]
Z_dat = dat[:,2]

# Convert from pandas dataframes to numpy arrays
X, Y, Z, = np.array([]), np.array([]), np.array([])
for i in range(len(X_dat)):
        X = np.append(X, X_dat[i])
        Y = np.append(Y, Y_dat[i])
        Z = np.append(Z, Z_dat[i])

# create x-y points to be used in heatmap
xi = np.linspace(X.min(), X.max(), 1000)
yi = np.linspace(Y.min(), Y.max(), 1000)

# Z is a matrix of x-y values
zi = griddata((X, Y), Z, (xi[None,:], yi[:,None]), method='cubic')

# I control the range of my colorbar by removing data 
# outside of my range of interest
zmin = 3
zmax = 12
zi[(zi<zmin) | (zi>zmax)] = None

# Create the contour plot
CS = plt.contourf(xi, yi, zi, 15, cmap=plt.cm.rainbow,
                  vmax=zmax, vmin=zmin)
plt.colorbar()  
plt.show()

where dat.xyz is in the form

x1 y1 z1
x2 y2 z2
...

将用户添加到Django中的组

问题:将用户添加到Django中的组

如何通过组名将用户添加到django中的组?

我可以做这个:

user.groups.add(1) # add by id

我将如何做这样的事情:

user.groups.add(name='groupname') # add by name

How would I add a user to a group in django by the group’s name?

I can do this:

user.groups.add(1) # add by id

How would I do something like this:

user.groups.add(name='groupname') # add by name

回答 0

使用具有组名称的“组模型”查找组,然后将用户添加到user_set

from django.contrib.auth.models import Group
my_group = Group.objects.get(name='my_group_name') 
my_group.user_set.add(your_user)

Find the group using Group model with the name of the group, then add the user to the user_set

from django.contrib.auth.models import Group
my_group = Group.objects.get(name='my_group_name') 
my_group.user_set.add(your_user)

回答 1

这是在现代版本的Django(在Django 1.7中测试)中如何执行此操作:

from django.contrib.auth.models import Group
group = Group.objects.get(name='groupname')
user.groups.add(group)

Here’s how to do this in modern versions of Django (tested in Django 1.7):

from django.contrib.auth.models import Group
group = Group.objects.get(name='groupname')
user.groups.add(group)

matplotlib:如何在图像上绘制矩形

问题:matplotlib:如何在图像上绘制矩形

如何在图像上绘制矩形,如下所示:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
im = np.array(Image.open('dog.png'), dtype=np.uint8)
plt.imshow(im)

我不知道该如何进行。

How to draw a rectangle on an image, like this:

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
im = np.array(Image.open('dog.png'), dtype=np.uint8)
plt.imshow(im)

I don’t know how to proceed.


回答 0

您可以将Rectangle补丁添加到matplotlib轴。

例如(在此处使用教程中的图像):

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
import numpy as np

im = np.array(Image.open('stinkbug.png'), dtype=np.uint8)

# Create figure and axes
fig,ax = plt.subplots(1)

# Display the image
ax.imshow(im)

# Create a Rectangle patch
rect = patches.Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

plt.show()

You can add a Rectangle patch to the matplotlib Axes.

For example (using the image from the tutorial here):

import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
import numpy as np

im = np.array(Image.open('stinkbug.png'), dtype=np.uint8)

# Create figure and axes
fig,ax = plt.subplots(1)

# Display the image
ax.imshow(im)

# Create a Rectangle patch
rect = patches.Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

plt.show()


回答 1

您需要使用补丁。

import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig2 = plt.figure()
ax2 = fig2.add_subplot(111, aspect='equal')

ax2.add_patch(
     patches.Rectangle(
        (0.1, 0.1),
        0.5,
        0.5,
        fill=False      # remove background
     ) ) 
fig2.savefig('rect2.png', dpi=90, bbox_inches='tight')

You need use patches.

import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig2 = plt.figure()
ax2 = fig2.add_subplot(111, aspect='equal')

ax2.add_patch(
     patches.Rectangle(
        (0.1, 0.1),
        0.5,
        0.5,
        fill=False      # remove background
     ) ) 
fig2.savefig('rect2.png', dpi=90, bbox_inches='tight')

回答 2

不需要子图,并且pyplot可以显示PIL图像,因此可以进一步简化:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

im = Image.open('stinkbug.png')

# Display the image
plt.imshow(im)

# Get the current reference
ax = plt.gca()

# Create a Rectangle patch
rect = Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

或者,简短版本:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

# Display the image
plt.imshow(Image.open('stinkbug.png'))

# Add the patch to the Axes
plt.gca().add_patch(Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none'))

There is no need for subplots, and pyplot can display PIL images, so this can be simplified further:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

im = Image.open('stinkbug.png')

# Display the image
plt.imshow(im)

# Get the current reference
ax = plt.gca()

# Create a Rectangle patch
rect = Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none')

# Add the patch to the Axes
ax.add_patch(rect)

Or, the short version:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from PIL import Image

# Display the image
plt.imshow(Image.open('stinkbug.png'))

# Add the patch to the Axes
plt.gca().add_patch(Rectangle((50,100),40,30,linewidth=1,edgecolor='r',facecolor='none'))

回答 3

据我了解,matplotlib是一个绘图库。

如果要更改图像数据(例如,在图像上绘制矩形),则可以使用PIL的ImageDrawOpenCV或类似的东西。

这是PIL的ImageDraw方法来绘制矩形

这是OpenCV绘制矩形的方法之一

您的问题询问了有关Matplotlib的问题,但可能应该只是询问有关在图像上绘制矩形的问题。

这是另一个解决我想知道的问题的问题: 使用PIL在其中绘制一个矩形和一个文本

From my understanding matplotlib is a plotting library.

If you want to change the image data (e.g. draw a rectangle on an image), you could use PIL’s ImageDraw, OpenCV, or something similar.

Here is PIL’s ImageDraw method to draw a rectangle.

Here is one of OpenCV’s methods for drawing a rectangle.

Your question asked about Matplotlib, but probably should have just asked about drawing a rectangle on an image.

Here is another question which addresses what I think you wanted to know: Draw a rectangle and a text in it using PIL


在Windows 7上添加Python路径

问题:在Windows 7上添加Python路径

我一直在尝试在Windows 7上将Python路径添加到命令行中,但是无论我尝试哪种方法,似乎都没有任何效果。我使用了该set命令,尝试通过“编辑环境”变量提示符等添加它。

此外,如果我在命令行上运行set命令,它将列出此内容

python = c:\python27

但是它仍然无法识别Python命令。

阅读文档以及其他各种资源似乎无济于事。

编辑:为了进一步说明,我在编辑环境提示中将Python可执行文件的路径附加到PATH。似乎不起作用。

I’ve been trying to add the Python path to the command line on Windows 7, yet no matter the method I try, nothing seems to work. I’ve used the set command, I’ve tried adding it through the Edit Environment variables prompt etc.

Further more if I run the set command on the command line it lists this

python = c:\python27

Yet it still doesn’t recognize the Python command.

Reading the documentation, and various other sources hasn’t seemed to help.

Edit: Just to clarify further, I’ve appended the path of the Python executable to PATH in edit environment prompt. Doesn’t seem to work.


回答 0

  1. 按住Win并按Pause
  2. 单击高级系统设置。
  3. 单击环境变量。
  4. 追加;C:\python27Path变量。
  5. 重新启动命令提示符。
  1. Hold Win and press Pause.
  2. Click Advanced System Settings.
  3. Click Environment Variables.
  4. Append ;C:\python27 to the Path variable.
  5. Restart Command Prompt.

回答 1

在Windows中设置环境变量时,我在很多情况下都出错了。我认为我应该在这里分享我过去的一些错误,希望对别人有所帮助。(这些适用于所有环境变量,不仅适用于设置Python路径)

当心这些可能的错误:

  1. 杀死并重新打开您的Shell窗口:对环境变量进行更改后,您必须重新启动要对其进行测试的窗口。
  2. 设置变量时没有空间。请确保您添加;C:\Python27无任何空格。(通常C:\SomeOther; C:\Python27在分号后尝试使用空格(␣)是不正确的。)
  3. 阐明完整路径时,请使用向后斜线。尝试时会看到正斜杠,echo $PATH但只有反斜杠对我有用。
  4. 不要添加最后的反斜杠。只有C:\Python27C:\Python27\

希望这对某人有帮助。

When setting Environmental Variables in Windows, I have gone wrong on many, many occasions. I thought I should share a few of my past mistakes here hoping that it might help someone. (These apply to all Environmental Variables, not just when setting Python Path)

Watch out for these possible mistakes:

  1. Kill and reopen your shell window: Once you make a change to the ENVIRONMENTAL Variables, you have to restart the window you are testing it on.
  2. NO SPACES when setting the Variables. Make sure that you are adding the ;C:\Python27 WITHOUT any spaces. (It is common to try C:\SomeOther; C:\Python27 That space (␣) after the semicolon is not okay.)
  3. USE A BACKWARD SLASH when spelling out your full path. You will see forward slashes when you try echo $PATH but only backward slashes have worked for me.
  4. DO NOT ADD a final backslash. Only C:\Python27 NOT C:\Python27\

Hope this helps someone.


回答 2

以管理员权限打开cmd .exe(右键单击应用程序)。然后输入:

setx路径“%path%; C:\ Python27;”

请记住以分号结尾,并且不要包含斜杠。

Open cmd.exe with administrator privileges (right click on app). Then type:

setx path “%path%;C:\Python27;”

Remember to end with a semi-colon and don’t include a trailing slash.


回答 3

我已经很久没有这个问题了。我以各种方式将其添加到我的路径中,但这终于对我有用:

  1. 右键单击“我的电脑”
  2. 点击“属性”
  3. 点击侧面板中的“高级系统设置”
  4. 点击“环境变量”
  5. 点击系统变量下面的“新建”
  6. 输入名称pythonexe(或您想要的任何名称
  7. 在值输入路径你的Python(例如:C:\Python32\
  8. 现在,编辑Path变量(在系统部分),然后添加%pythonexe%;到已经存在的末尾

IDK为什么这样做有效,但对我有用。

然后尝试在命令行中输入“ python”,它应该可以工作!


编辑:

最近,我一直在使用该程序,它似乎运行良好。还有一个看起来也不错,尽管我从未尝试过。

I’ve had a problem with this for a LONG time. I added it to my path in every way I could think of but here’s what finally worked for me:

  1. Right click on “My computer”
  2. Click “Properties”
  3. Click “Advanced system settings” in the side panel
  4. Click “Environment Variables”
  5. Click the “New” below system variables
  6. in name enter pythonexe (or anything you want)
  7. in value enter the path to your python (example: C:\Python32\)
  8. Now edit the Path variable (in the system part) and add %pythonexe%; to the end of what’s already there

IDK why this works but it did for me.

then try typing “python” into your command line and it should work!


Edit:

Lately I’ve been using this program which seems to work pretty well. There’s also this one which looks pretty good too, although I’ve never tried it.


回答 4

尝试将此python.bat文件添加到System32文件夹,然后在键入时命令行将运行pythonpython

python.bat

@C:\Python27\python.exe %*

资源:

https://github.com/KartikTalwar/dotfiles/blob/master/bat/python.bat

Try adding this python.bat file to System32 folder and the command line will now run python when you type in python

python.bat

@C:\Python27\python.exe %*

Source:

https://github.com/KartikTalwar/dotfiles/blob/master/bat/python.bat


回答 5

您可以使用命令从当前cmd窗口设置路径PATH =。那只会为当前的cmd实例添加它。如果要永久添加,则应将其添加到系统变量。(计算机>高级系统设置>环境变量)

您将转到您的cmd实例,然后放入PATH=C:/Python27/;%PATH%

You can set the path from the current cmd window using the PATH = command. That will only add it for the current cmd instance. if you want to add it permanently, you should add it to system variables. (Computer > Advanced System Settings > Environment Variables)

You would goto your cmd instance, and put in PATH=C:/Python27/;%PATH%.


回答 6

确保您没有在新目录之前添加空格。

好:旧;旧;旧;新

不好:老;老;老;新

Make sure you don’t add a space before the new directory.

Good: old;old;old;new

Bad: old;old;old; new


回答 7

Python带有一个小型工具,可以执行此操作。从命令行运行:

c:\python27\tools\scripts\win_add2path.py

确保关闭命令窗口(使用exit或关闭按钮),然后再次打开它。

Python comes with a small utility that does just this. From the command line run:

c:\python27\tools\scripts\win_add2path.py

Make sure you close the command window (with exit or the close button) and open it again.


回答 8

以下程序将python可执行路径和subdir脚本(例如pip和easy_install的安装位置)添加到您的环境中。它从绑定.py扩展名的注册表项中找到python可执行文件的路径。它将删除您环境中的旧python路径。也适用于XP(可能还有Vista)。它仅使用基本Windows安装程序随附的模块。

# coding: utf-8

import sys
import os
import time
import _winreg
import ctypes

def find_python():
    """
    retrieves the commandline for .py extensions from the registry
    """
    hKey = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,
                           r'Python.File\shell\open\command')
    # get the default value
    value, typ = _winreg.QueryValueEx (hKey, None)
    program = value.split('"')[1]
    if not program.lower().endswith(r'\python.exe'):
        return None
    return os.path.dirname(program)

def extend_path(pypath, remove=False, verbose=0, remove_old=True,
                script=False):
    """
    extend(pypath) adds pypath to the PATH env. variable as defined in the
    registry, and then notifies applications (e.g. the desktop) of this change.
    !!! Already opened DOS-Command prompts are not updated. !!!
    Newly opened prompts will have the new path (inherited from the 
    updated windows explorer desktop)
    options:
    remove (default unset), remove from PATH instead of extend PATH
    remove_old (default set), removes any (old) python paths first
    script (default unset), try to add/remove the Scripts subdirectory 
        of pypath (pip, easy_install) as well
    """
    _sd = 'Scripts' # scripts subdir
    hKey = _winreg.OpenKey (_winreg.HKEY_LOCAL_MACHINE,
               r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
               0, _winreg.KEY_READ | _winreg.KEY_SET_VALUE)

    value, typ = _winreg.QueryValueEx (hKey, "PATH")
    vals = value.split(';')
    assert isinstance(vals, list)
    if not remove and remove_old:
        new_vals = []
        for v in vals:
            pyexe = os.path.join(v, 'python.exe')
            if v != pypath and os.path.exists(pyexe):
                if verbose > 0:
                    print 'removing from PATH:', v
                continue
            if script and v != os.path.join(pypath, _sd) and \
               os.path.exists(v.replace(_sd, pyexe)):
                if verbose > 0:
                    print 'removing from PATH:', v
                continue
            new_vals.append(v)
        vals = new_vals
    if remove:
        try:
            vals.remove(pypath)
        except ValueError:
            if verbose > 0:
                print 'path element', pypath, 'not found'
            return
        if script:
            try:
                vals.remove(os.path.join(pypath, _sd))
            except ValueError:
                pass
            print 'removing from PATH:', pypath
    else:
        if pypath in vals:
            if verbose > 0:
                print 'path element', pypath, 'already in PATH'
            return
        vals.append(pypath)
        if verbose > 1:
            print 'adding to PATH:', pypath
        if script:
            if not pypath + '\\Scripts' in vals:
                vals.append(pypath + '\\Scripts')
            if verbose > 1:
                print 'adding to PATH:', pypath + '\\Scripts'
    _winreg.SetValueEx(hKey, "PATH", 0, typ, ';'.join(vals) )
    _winreg.SetValueEx(hKey, "OLDPATH", 0, typ, value )
    _winreg.FlushKey(hKey)
    # notify other programs
    SendMessage = ctypes.windll.user32.SendMessageW
    HWND_BROADCAST = 0xFFFF
    WM_SETTINGCHANGE = 0x1A
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u'Environment')
    if verbose > 1:
        print 'Do not forget to restart any command prompts'

if __name__ == '__main__':
    remove = '--remove' in sys.argv
    script = '--noscripts' not in sys.argv
    extend_path(find_python(), verbose=2, remove=remove, script=script)

The following program will add the python executable path and the subdir Scripts (which is where e.g. pip and easy_install are installed) to your environment. It finds the path to the python executable from the registry key binding the .py extension. It will remove old python paths in your environment. Works with XP (and probably Vista) as well. It only uses modules that come with the basic windows installer.

# coding: utf-8

import sys
import os
import time
import _winreg
import ctypes

def find_python():
    """
    retrieves the commandline for .py extensions from the registry
    """
    hKey = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,
                           r'Python.File\shell\open\command')
    # get the default value
    value, typ = _winreg.QueryValueEx (hKey, None)
    program = value.split('"')[1]
    if not program.lower().endswith(r'\python.exe'):
        return None
    return os.path.dirname(program)

def extend_path(pypath, remove=False, verbose=0, remove_old=True,
                script=False):
    """
    extend(pypath) adds pypath to the PATH env. variable as defined in the
    registry, and then notifies applications (e.g. the desktop) of this change.
    !!! Already opened DOS-Command prompts are not updated. !!!
    Newly opened prompts will have the new path (inherited from the 
    updated windows explorer desktop)
    options:
    remove (default unset), remove from PATH instead of extend PATH
    remove_old (default set), removes any (old) python paths first
    script (default unset), try to add/remove the Scripts subdirectory 
        of pypath (pip, easy_install) as well
    """
    _sd = 'Scripts' # scripts subdir
    hKey = _winreg.OpenKey (_winreg.HKEY_LOCAL_MACHINE,
               r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
               0, _winreg.KEY_READ | _winreg.KEY_SET_VALUE)

    value, typ = _winreg.QueryValueEx (hKey, "PATH")
    vals = value.split(';')
    assert isinstance(vals, list)
    if not remove and remove_old:
        new_vals = []
        for v in vals:
            pyexe = os.path.join(v, 'python.exe')
            if v != pypath and os.path.exists(pyexe):
                if verbose > 0:
                    print 'removing from PATH:', v
                continue
            if script and v != os.path.join(pypath, _sd) and \
               os.path.exists(v.replace(_sd, pyexe)):
                if verbose > 0:
                    print 'removing from PATH:', v
                continue
            new_vals.append(v)
        vals = new_vals
    if remove:
        try:
            vals.remove(pypath)
        except ValueError:
            if verbose > 0:
                print 'path element', pypath, 'not found'
            return
        if script:
            try:
                vals.remove(os.path.join(pypath, _sd))
            except ValueError:
                pass
            print 'removing from PATH:', pypath
    else:
        if pypath in vals:
            if verbose > 0:
                print 'path element', pypath, 'already in PATH'
            return
        vals.append(pypath)
        if verbose > 1:
            print 'adding to PATH:', pypath
        if script:
            if not pypath + '\\Scripts' in vals:
                vals.append(pypath + '\\Scripts')
            if verbose > 1:
                print 'adding to PATH:', pypath + '\\Scripts'
    _winreg.SetValueEx(hKey, "PATH", 0, typ, ';'.join(vals) )
    _winreg.SetValueEx(hKey, "OLDPATH", 0, typ, value )
    _winreg.FlushKey(hKey)
    # notify other programs
    SendMessage = ctypes.windll.user32.SendMessageW
    HWND_BROADCAST = 0xFFFF
    WM_SETTINGCHANGE = 0x1A
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u'Environment')
    if verbose > 1:
        print 'Do not forget to restart any command prompts'

if __name__ == '__main__':
    remove = '--remove' in sys.argv
    script = '--noscripts' not in sys.argv
    extend_path(find_python(), verbose=2, remove=remove, script=script)

回答 9

我知道这篇文章很旧,但我想补充一点,该解决方案假设使用admin privs。如果您没有这些,可以:

转到控制面板,键入路径(此为Windows 7,现在在搜索框中),然后单击“为您的帐户编辑环境变量”。现在,您将看到环境变量对话框,其顶部为“用户变量”,而其下方为“系统变量”。

您可以作为用户单击顶部的“新建”按钮并添加:

变量名称:PATH
变量值:C:\ Python27

(任何地方都没有空格),然后单击“确定”。重新启动命令提示符后,User变量中的所有PATH都将附加到系统路径的末尾。它不会以任何其他方式替换PATH。

如果要设置特定的完整路径,最好创建一个像这样的批处理文件:

@echo off
PATH C:\User\Me\Programs\mingw\bin;C:\User\Me\Programs;C:\Windows\system32
title Compiler Environment - %Username%@%Computername%
cmd

将其命名为“ compiler.bat”或双击以启动它。或链接到它。或固定等等…

I know this post is old but I’d like to add that the solutions assume admin privs. If you don’t have those you can:

Go to control panel, type path (this is Windows 7 now so that’s in the Search box) and click “Edit Environment variables for your account”. You’ll now see the Environment Variable dialog with “User variables” on the top and “System variables” below.

You can, as a user, click the top “New” button and add:

Variable name: PATH
Variable value: C:\Python27

(no spaces anywhere) and click OK. Once your command prompt is restarted, any PATH in the User variables is appended to the end of the System Path. It doesn’t replace the PATH in any other way.

If you want a specific full path set up, you’re better off creating a batch file like this little one:

@echo off
PATH C:\User\Me\Programs\mingw\bin;C:\User\Me\Programs;C:\Windows\system32
title Compiler Environment - %Username%@%Computername%
cmd

Call it “compiler.bat” or whatever and double click to start it. Or link to it. Or pin it etc…


回答 10

您需要在系统变量中进行更改
-右键单击“我的电脑”
-单击“属性”
-单击侧面板中的“高级系统设置”
-单击环境变量-您将分为两部分变量和系统变量
-在系统变量部分下搜索变量’Path’单击编辑并添加
"C:\Python27;"(不带引号)将其保存
-现在打开命令行类型’path’ 并按Enter,您将看到路径变量已被修改
-现在输入python --version您将看到python版本

完成了

You need to make changes in your system variable
— Right click on “My computer”
— Click “Properties”
— Click “Advanced system settings” in the side panel
— Click on Environment Variable — You will two sections of user variable and system variable
— Under system variable section search for the variable ‘Path’ click on edit and add
"C:\Python27;" (without quotes) save it
— Now open command line type ‘path’ hit enter you will see path variable has been modified
— Now type python --version you will see the python version

And it is done


回答 11

对于尝试使用Python 3.3+实现此目标的任何人,Windows安装程序现在都提供了一个将python.exe添加到系统搜索路径的选项。在docs中阅读更多内容。

For anyone trying to achieve this with Python 3.3+, the Windows installer now includes an option to add python.exe to the system search path. Read more in the docs.


回答 12

使用Windows环境变量始终是一种可怕的经历。最近,我发现了一个令人称奇的工具,称为Rapid Environment Editor,它提供了非常简单的GUI来管理它们。

如果您使用Chocolatey,则可以使用安装它choco install rapidee。否则,请访问http://www.rapidee.com/cn/download

重新阅读此内容,听起来像是有偿的,但是我发誓我不是!一段时间以来,它一直是我工具箱中最有用的实用程序之一,但令我惊讶的是似乎没人知道它。

Working with Windows environment variables is always a horrible experience. Recently, I found an amazing tool called Rapid Environment Editor, which gives an awesomely simple GUI for managing them.

If you use chocolatey, you can install it using choco install rapidee. Otherwise, take a look at http://www.rapidee.com/en/download

Re-reading this, it sounds like a paid shill, but I swear I’m not! It’s just been one of the most useful utilities in my toolkit for a while and I’m surprised no one seems to know about it.


回答 13

如果Python与其他程序一起安装,例如我的ArcGIS 10.1,则还必须在环境变量中包含指向python.exe路径的所有其他文件夹。

所以我的环境变量看起来像这样:

系统变量>路径>添加 ;C:\Python27\ArcGIS10.1

If Python was installed with another program, such as ArcGIS 10.1 in my case, then you also must include any extra folders that path to the python.exe in your Environment Variables.

So my Environment Variables looks like this:

System variables > Path > add ;C:\Python27\ArcGIS10.1


回答 14

这个问题已经很老了,但是我遇到了一个类似的问题,这里没有列出我的特定解决方案:

确保您的PATH中没有不存在的文件夹。

就我而言,我有一堆默认文件夹(Windows,Powershell,Sql Server等),然后是C:\bin我通常使用的自定义,然后进行了其他各种调整,例如c:\python17等等。事实证明,cmd处理器发现c:\bin没有不存在,然后停止处理其余变量。

另外,我不知道如果没有PATH manager,我是否会注意到这一点。它很好地强调了该项目无效的事实。

This question is pretty old, but I just ran into a similar problem and my particular solution wasn’t listed here:

Make sure you don’t have a folder in your PATH that doesn’t exist.

In my case, I had a bunch of default folders (Windows, Powershell, Sql Server, etc) and then a custom C:\bin that I typically use, and then various other tweaks like c:\python17, etc. It turns out that the cmd processor was finding that c:\bin didn’t exist and then stopped processing the rest of the variable.

Also, I don’t know that I ever would have noticed this without PATH manager. It nicely highlighted the fact that that item was invalid.


回答 15

我刚刚使用选项“将python添加到PATH”在Windows 7上安装了Python 3.3。

在PATH变量中,安装程序会自动添加最后一个反斜杠C:\Python33\ ,因此在命令提示符下不起作用(我尝试多次关闭/打开提示符)

我删除了最后的反斜杠,然后它起作用了:C:\Python33

感谢Ram Narasimhan给您的提示4!

I just installed Python 3.3 on Windows 7 using the option “add python to PATH”.

In PATH variable, the installer automatically added a final backslash: C:\Python33\ and so it did not work on command prompt (i tried closing/opening the prompt several times)

I removed the final backslash and then it worked: C:\Python33

Thanks Ram Narasimhan for your tip #4 !


回答 16

我使用cmd在Win7 64位下组织了这样的python环境变量。

PYTHONPATH通过Windows的环境变量菜单设置变量,并将其添加%PYTHONPATH%PATH变量中:

...;%PYTHONPATH%

cmd shell将变量正确扩展为:

C:\>echo %PYTHONPATH%
C:\python27;c:\python27\lib;C:\python27\scripts

不要忘记在更改PATH之后重新启动cmd shell。

I organized my python environment variable like this under Win7 64-bit using cmd.

I set the variable PYTHONPATH via environment variable menue of windows and added %PYTHONPATH% to the PATH variable:

...;%PYTHONPATH%

The cmd shell expands the variable correctly to this:

C:\>echo %PYTHONPATH%
C:\python27;c:\python27\lib;C:\python27\scripts

Do not forget to restart cmd shell after changing PATH.


回答 17

将其写在命令提示符上:

set Path=%path%

用Python文件夹示例的路径替换%path%:

set Path=C:/Python27

write that on your Command Prompt:

set Path=%path%

Replace %path% by the Path of your Python Folder Example:

set Path=C:/Python27

回答 18

如果您对设置python的路径感到沮丧,只需下载新版本的python并卸载旧版本的python,并在安装新版本时询问是否设置路径标记并安装

这是最好的方法

If you have got frustrated by setting the path for the python just download the new version of python uninstall the older version of the python and while installing the new version it will ask whether to set path mark that and install

its the best way