标签归档:Python

如何在Python中“测试” NoneType?

问题:如何在Python中“测试” NoneType?

我有一个有时返回NoneType值的方法。那么我如何质疑一个无类型的变量呢?例如,我需要使用if方法

if not new:
    new = '#'

我知道这是错误的方式,希望您能理解我的意思。

I have a method that sometimes returns a NoneType value. So how can I question a variable that is a NoneType? I need to use if method, for example

if not new:
    new = '#'

I know that is the wrong way and I hope you understand what I meant.


回答 0

那么我如何质疑一个无类型的变量呢?

is像这样使用运算符

if variable is None:

为什么这样有效?

由于NoneNoneTypePython中唯一的单例对象,因此我们可以使用isoperator来检查变量None中是否包含变量。

引用is文档

运算符isis not对象身份测试:x is y当且仅当xy是相同对象时,才为true 。x is not y产生反真值。

由于只能有一个实例Noneis因此是检查的首选方法None


从马口中听到

引用Python的编码样式指南-PEP-008(由Guido亲自定义),

与单例之类的比较None应该总是用isis not不是等式运算符进行

So how can I question a variable that is a NoneType?

Use is operator, like this

if variable is None:

Why this works?

Since None is the sole singleton object of NoneType in Python, we can use is operator to check if a variable has None in it or not.

Quoting from is docs,

The operators is and is not test for object identity: x is y is true if and only if x and y are the same object. x is not y yields the inverse truth value.

Since there can be only one instance of None, is would be the preferred way to check None.


Hear it from the horse’s mouth

Quoting Python’s Coding Style Guidelines – PEP-008 (jointly defined by Guido himself),

Comparisons to singletons like None should always be done with is or is not, never the equality operators.


回答 1

if variable is None:
   ...

if variable is not None:
   ...
if variable is None:
   ...

if variable is not None:
   ...

回答 2

也可以isinstance按照Alex Hall的回答来完成:

>>> NoneType = type(None)
>>> x = None
>>> type(x) == NoneType
True
>>> isinstance(x, NoneType)
True

isinstance 也很直观,但有一个复杂之处,那就是需要

NoneType = type(None)

对于像int和这样的类型,则不需要float

It can also be done with isinstance as per Alex Hall’s answer :

>>> NoneType = type(None)
>>> x = None
>>> type(x) == NoneType
True
>>> isinstance(x, NoneType)
True

isinstance is also intuitive but there is the complication that it requires the line

NoneType = type(None)

which isn’t needed for types like int and float.


回答 3

正如亚伦·霍尔的评论所指出的:

由于您不能继承子类,NoneType并且由于None是单例,isinstance因此不应将其用于检测None-而是应按照已接受的答案进行操作,并使用is Noneis not None


原始答案:

但是,最简单的方法,除了豆蔻果实的答案外,没有多余内容可能是:
isinstance(x, type(None))

那么我如何质疑一个无类型的变量呢?我需要使用if方法

使用isinstance()不需要is的内if语句来:

if isinstance(x, type(None)): 
    #do stuff

其他信息
您还可以isinstance()按照文档中的说明在一个语句中检查多种类型。只需将类型写为元组即可。

isinstance(x, (type(None), bytes))

As pointed out by Aaron Hall’s comment:

Since you can’t subclass NoneType and since None is a singleton, isinstance should not be used to detect None – instead you should do as the accepted answer says, and use is None or is not None.


Original Answer:

The simplest way however, without the extra line in addition to cardamom’s answer is probably:
isinstance(x, type(None))

So how can I question a variable that is a NoneType? I need to use if method

Using isinstance() does not require an is within the if-statement:

if isinstance(x, type(None)): 
    #do stuff

Additional information
You can also check for multiple types in one isinstance() statement as mentioned in the documentation. Just write the types as a tuple.

isinstance(x, (type(None), bytes))

回答 4

不知道这是否能回答问题。但是我知道这花了我一段时间才能弄清楚。我浏览了一个网站,突然间,作者的名字不再存在。因此需要一个检查语句。

if type(author) == type(None):
     my if body
else:
    my else body

在这种情况下,作者可以是任何变量,也None可以是您要检查的任何类型。

Not sure if this answers the question. But I know this took me a while to figure out. I was looping through a website and all of sudden the name of the authors weren’t there anymore. So needed a check statement.

if type(author) == type(None):
     my if body
else:
    my else body

Author can be any variable in this case, and None can be any type that you are checking for.


回答 5

Python 2.7:

x = None
isinstance(x, type(None))

要么

isinstance(None, type(None))

==>正确

Python 2.7 :

x = None
isinstance(x, type(None))

or

isinstance(None, type(None))

==> True


回答 6

希望这个例子对您有帮助)

print(type(None) # NoneType

因此,您可以检查变量名称的类型

#Example
name = 12 # name = None
if type(name) != type(None):
    print(name)
else:
    print("Can't find name")

I hope this example will be helpful for you)

print(type(None) # NoneType

So, you can check type of the variable name

#Example
name = 12 # name = None
if type(name) != type(None):
    print(name)
else:
    print("Can't find name")

pip安装失败,并显示“连接错误:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败(_ssl.c:598)”

问题:pip安装失败,并显示“连接错误:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败(_ssl.c:598)”

我是Python的新手,并尝试> pip install linkchecker在Windows 7上使用。

  • 无论软件包如何,pip安装都会失败。例如,> pip install scrapy还会导致SSL错误。
  • 原始安装的Python 3.4.1包含pip 1.5.6。我尝试做的第一件事是安装linkchecker。Python 2.7已经安装,它是ArcGIS附带的。python并且pip直到我安装3.4.1时才可从命令行使用。
  • > pip search linkchecker作品。可能是因为点子搜索无法验证站点的SSL证书。
  • 我在公司网络中,但是我们没有通过代理访问Internet。
  • 每台公司计算机(包括我的计算机)都具有受信任的根证书颁发机构,该证书颁发机构出于各种原因而被使用,包括启用对到https://google.com的 TLS流量的监视。不确定是否与此有关。

这是运行后我的pip.log的内容pip install linkchecker

Downloading/unpacking linkchecker
  Getting page https://pypi.python.org/simple/linkchecker/
  Could not fetch URL https://pypi.python.org/simple/linkchecker/: connection error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)
  Will skip URL https://pypi.python.org/simple/linkchecker/ when looking for download links for linkchecker
  Getting page https://pypi.python.org/simple/
  Could not fetch URL https://pypi.python.org/simple/: connection error: HTTPSConnectionPool(host='pypi.python.org', port=443): Max retries exceeded with url: /simple/ (Caused by <class 'http.client.CannotSendRequest'>: Request-sent)
  Will skip URL https://pypi.python.org/simple/ when looking for download links for linkchecker
  Cannot fetch index base URL https://pypi.python.org/simple/
  URLs to search for versions for linkchecker:
  * https://pypi.python.org/simple/linkchecker/
  Getting page https://pypi.python.org/simple/linkchecker/
  Could not fetch URL https://pypi.python.org/simple/linkchecker/: connection error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)
  Will skip URL https://pypi.python.org/simple/linkchecker/ when looking for download links for linkchecker
  Could not find any downloads that satisfy the requirement linkchecker
Cleaning up...
  Removing temporary dir C:\Users\jcook\AppData\Local\Temp\pip_build_jcook...
No distributions at all found for linkchecker
Exception information:
Traceback (most recent call last):
  File "C:\Python34\lib\site-packages\pip\basecommand.py", line 122, in main
    status = self.run(options, args)
  File "C:\Python34\lib\site-packages\pip\commands\install.py", line 278, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File "C:\Python34\lib\site-packages\pip\req.py", line 1177, in prepare_files
    url = finder.find_requirement(req_to_install, upgrade=self.upgrade)
  File "C:\Python34\lib\site-packages\pip\index.py", line 277, in find_requirement
    raise DistributionNotFound('No distributions at all found for %s' % req)
pip.exceptions.DistributionNotFound: No distributions at all found for linkchecker

I am very new to Python and trying to > pip install linkchecker on Windows 7. Some notes:

  • pip install is failing no matter the package. For example, > pip install scrapy also results in the SSL error.
  • Vanilla install of Python 3.4.1 included pip 1.5.6. The first thing I tried to do was install linkchecker. Python 2.7 was already installed, it came with ArcGIS. python and pip were not available from the command line until I installed 3.4.1.
  • > pip search linkchecker works. Perhaps that is because pip search does not verify the site’s SSL certificate.
  • I am in a company network but we do not go through a proxy to reach the Internet.
  • Each company computer (including mine) has a Trusted Root Certificate Authority that is used for various reasons including enabling monitoring TLS traffic to https://google.com. Not sure if that has anything to do with it.

Here are the contents of my pip.log after running pip install linkchecker:

Downloading/unpacking linkchecker
  Getting page https://pypi.python.org/simple/linkchecker/
  Could not fetch URL https://pypi.python.org/simple/linkchecker/: connection error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)
  Will skip URL https://pypi.python.org/simple/linkchecker/ when looking for download links for linkchecker
  Getting page https://pypi.python.org/simple/
  Could not fetch URL https://pypi.python.org/simple/: connection error: HTTPSConnectionPool(host='pypi.python.org', port=443): Max retries exceeded with url: /simple/ (Caused by <class 'http.client.CannotSendRequest'>: Request-sent)
  Will skip URL https://pypi.python.org/simple/ when looking for download links for linkchecker
  Cannot fetch index base URL https://pypi.python.org/simple/
  URLs to search for versions for linkchecker:
  * https://pypi.python.org/simple/linkchecker/
  Getting page https://pypi.python.org/simple/linkchecker/
  Could not fetch URL https://pypi.python.org/simple/linkchecker/: connection error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:598)
  Will skip URL https://pypi.python.org/simple/linkchecker/ when looking for download links for linkchecker
  Could not find any downloads that satisfy the requirement linkchecker
Cleaning up...
  Removing temporary dir C:\Users\jcook\AppData\Local\Temp\pip_build_jcook...
No distributions at all found for linkchecker
Exception information:
Traceback (most recent call last):
  File "C:\Python34\lib\site-packages\pip\basecommand.py", line 122, in main
    status = self.run(options, args)
  File "C:\Python34\lib\site-packages\pip\commands\install.py", line 278, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File "C:\Python34\lib\site-packages\pip\req.py", line 1177, in prepare_files
    url = finder.find_requirement(req_to_install, upgrade=self.upgrade)
  File "C:\Python34\lib\site-packages\pip\index.py", line 277, in find_requirement
    raise DistributionNotFound('No distributions at all found for %s' % req)
pip.exceptions.DistributionNotFound: No distributions at all found for linkchecker

回答 0

—–> pip install gensim config –global http.sslVerify否

只需使用“ config –global http.sslVerify false”语句安装任何软件包

您可以通过将pypi.org和设置files.pythonhosted.org为受信任的主机来忽略SSL错误。

$ pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org <package_name>

注意:在2018年4月的某个时候,Python软件包索引从迁移pypi.python.orgpypi.org。这意味着使用旧域的“受信任主机”命令不再起作用。

永久修复

自发布pip 10.0起,您应该能够通过pip自我升级永久解决此问题:

$ pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org pip setuptools

或者通过重新安装以获得最新版本:

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

(…,然后get-pip.py与相关的Python解释器一起运行)。

pip install <otherpackage>应该在此之后工作。如果没有,那么您将需要做更多的事情,如下所述。


您可能需要将信任的主机和代理添加到配置文件中

pip.ini(Windows)或pip.conf(unix)

[global]
trusted-host = pypi.python.org
               pypi.org
               files.pythonhosted.org

替代解决方案(安全程度较低)

大多数答案可能会带来安全问题。

帮助轻松安装大多数python软件包的两个解决方法是:

  • 使用easy_install:如果您确实很懒,不想浪费很多时间,请使用easy_install <package_name>。请注意,找不到某些软件包,或者会产生一些小错误。
  • 使用Wheel:下载python软件包Wheel并使用pip命令pip install wheel_package_name.whl安装该软件包。

—–> pip install gensim config –global http.sslVerify false

Just install any package with the “config –global http.sslVerify false” statement

You can ignore SSL errors by setting pypi.org and files.pythonhosted.org as trusted hosts.

$ pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org <package_name>

Note: Sometime during April 2018, the Python Package Index was migrated from pypi.python.org to pypi.org. This means “trusted-host” commands using the old domain no longer work.

Permanent Fix

Since the release of pip 10.0, you should be able to fix this permanently just by upgrading pip itself:

$ pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org pip setuptools

Or by just reinstalling it to get the latest version:

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

(… and then running get-pip.py with the relevant Python interpreter).

pip install <otherpackage> should just work after this. If not, then you will need to do more, as explained below.


You may want to add the trusted hosts and proxy to your config file.

pip.ini (Windows) or pip.conf (unix)

[global]
trusted-host = pypi.python.org
               pypi.org
               files.pythonhosted.org

Alternate Solutions (Less secure)

Most of the answers could pose a security issue.

Two of the workarounds that help in installing most of the python packages with ease would be:

  • Using easy_install: if you are really lazy and don’t want to waste much time, use easy_install <package_name>. Note that some packages won’t be found or will give small errors.
  • Using Wheel: download the Wheel of the python package and use the pip command pip install wheel_package_name.whl to install the package.

回答 1

您可以使用以下参数指定证书:

pip --cert /etc/ssl/certs/FOO_Root_CA.pem install linkchecker

请参阅:文档»参考指南»点

如果指定您公司的根证书无效,则可能无法使用cURL:http : //curl.haxx.se/ca/cacert.pem

您必须使用PEM文件而不是CRT文件。如果您有CRT文件,则需要将该文件转换为PEM。注释中有报告说,该报告现在可用于CRT文件,但我尚未验证。

还要检查:SSL证书验证

You can specify a cert with this param:

pip --cert /etc/ssl/certs/FOO_Root_CA.pem install linkchecker

See: Docs » Reference Guide » pip

If specifying your company’s root cert doesn’t work maybe the cURL one will work: http://curl.haxx.se/ca/cacert.pem

You must use a PEM file and not a CRT file. If you have a CRT file you will need to convert the file to PEM There are reports in the comments that this now works with a CRT file but I have not verified.

Also check: SSL Cert Verification.


回答 2

kenorb的答案非常有用(而且很棒!)。
在他的解决方案中,也许这是最简单的解决方案: --trusted-host

例如,在这种情况下,您可以

pip install --trusted-host pypi.python.org linkchecker

不需要pem文件(或其他任何文件)。

kenorb’s answer is very useful (and great!).
Among his solutions, maybe this is the most simple one: --trusted-host

For example, in this case you can do

pip install --trusted-host pypi.python.org linkchecker

The pem file(or anything else) is unnecessary.


回答 3

对我来说,问题的解决,创建一个文件夹 pip,一个文件:pip.iniC:\Users\<username>\AppData\Roaming\ 例如:

C:\Users\<username>\AppData\Roaming\pip\pip.ini

我在里面写道:

[global]
trusted-host = pypi.python.org
               pypi.org
               files.pythonhosted.org

我重新启动python,然后pip永久信任这些站点,并使用它们从中下载软件包。

如果在Windows上找不到AppData文件夹,请写入%appdata%文件资源管理器,它将出现。

For me the problem was fixed by creating a folder pip, with a file: pip.ini in C:\Users\<username>\AppData\Roaming\ e.g:

C:\Users\<username>\AppData\Roaming\pip\pip.ini

Inside it I wrote:

[global]
trusted-host = pypi.python.org
               pypi.org
               files.pythonhosted.org

I restarted python, and then pip permanently trusted these sites, and used them to download packages from.

If you can’t find the AppData Folder on windows, write %appdata% in file explorer and it should appear.


回答 4

答案是非常相似的,并且有些令人困惑。就我而言,就是公司网络中的证书。我能够使用以下方法解决该问题:

pip install --trusted-host files.pythonhosted.org --trusted-host pypi.org --trusted-host pypi.python.org oauthlib -vvv

如这里所见。如果不需要详细的输出,则可以省略-vvv参数

The answers are quite similar and a bit confusing. In my case, the certificates in my company’s network was the issue. I was able to work around the problem using:

pip install --trusted-host files.pythonhosted.org --trusted-host pypi.org --trusted-host pypi.python.org oauthlib -vvv

As seen here. The -vvv argument can be omited if verbose output is not required


回答 5

永久修复

pip install --upgrade pip --trusted-host pypi.org --trusted-host files.pythonhosted.org

例如:

pip install <package name> --trusted-host pypi.org --trusted-host files.pythonhosted.org

Permanent Fix

pip install --upgrade pip --trusted-host pypi.org --trusted-host files.pythonhosted.org

For eg:

pip install <package name> --trusted-host pypi.org --trusted-host files.pythonhosted.org

回答 6

要一劳永逸地解决此问题,您可以验证您是否有pip.conf文件。

pip.conf根据文档,这是您应该在的位置:

在Unix上,默认配置文件是:$HOME/.config/pip/pip.conf尊重XDG_CONFIG_HOME环境变量。

在macOS上,配置文件是$HOME/Library/Application Support/pip/pip.conf目录是否$HOME/Library/Application Support/pip存在$HOME/.config/pip/pip.conf

在Windows上,配置文件为%APPDATA%\pip\pip.ini

在virtualenv内部:

在Unix和macOS上,文件为 $VIRTUAL_ENV/pip.conf

在Windows上,文件为: %VIRTUAL_ENV%\pip.ini

pip.conf应该看起来像:

[global]
trusted-host = pypi.python.org

pip install linkcheckerlinkchecker创建pip.conf文件后安装无投诉。

To solve this problem once and for all, you can verify that you have a pip.conf file.

This is where your pip.conf should be, according to the documentation:

On Unix the default configuration file is: $HOME/.config/pip/pip.conf which respects the XDG_CONFIG_HOME environment variable.

On macOS the configuration file is $HOME/Library/Application Support/pip/pip.conf if directory $HOME/Library/Application Support/pip exists else $HOME/.config/pip/pip.conf

On Windows the configuration file is %APPDATA%\pip\pip.ini.

Inside a virtualenv:

On Unix and macOS the file is $VIRTUAL_ENV/pip.conf

On Windows the file is: %VIRTUAL_ENV%\pip.ini

Your pip.conf should look like:

[global]
trusted-host = pypi.python.org

pip install linkchecker installed linkchecker without complains after I created the pip.conf file.


回答 7

我发现的最直接的方法是,从https://www.digicert.com/digicert-root-certificates.htm#roots从DigiCert下载和使用“ DigiCert高保证EV根CA”。

您可以通过单击地址栏中的锁定图标来访问https://pypi.python.org/以验证证书颁发者,或通过使用openssl来提高您的怪胎信誉:

$ openssl s_client -connect pypi.python.org:443
CONNECTED(00000003)
depth=1 /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/businessCategory=Private Organization/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/serialNumber=3359300/street=16 Allen Rd/postalCode=03894-4801/C=US/ST=NH/L=Wolfeboro,/O=Python Software Foundation/CN=www.python.org
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA

证书链中的最后一个CN值是您需要下载的CA的名称。

要一次性完成,请执行以下操作:

  1. 从DigiCert 下载CRT
  2. 将CRT转换为PEM格式
  3. 将PIP_CERT环境变量导出到PEM文件的路径

(最后一行假设您正在使用bash shell)在运行pip之前。

curl -sO http://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt 
openssl x509 -inform DES -in DigiCertHighAssuranceEVRootCA.crt -out DigiCertHighAssuranceEVRootCA.pem -text
export PIP_CERT=`pwd`/DigiCertHighAssuranceEVRootCA.pem

为了使其可重复使用,请将DigiCertHighAssuranceEVRootCA.crt放在公共位置,然后在〜/ .bashrc中相应地导出PIP_CERT。

The most straightforward way I’ve found, is to download and use the “DigiCert High Assurance EV Root CA” from DigiCert at https://www.digicert.com/digicert-root-certificates.htm#roots

You can visit https://pypi.python.org/ to verify the cert issuer by clicking on the lock icon in the address bar, or increase your geek cred by using openssl:

$ openssl s_client -connect pypi.python.org:443
CONNECTED(00000003)
depth=1 /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/businessCategory=Private Organization/1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/serialNumber=3359300/street=16 Allen Rd/postalCode=03894-4801/C=US/ST=NH/L=Wolfeboro,/O=Python Software Foundation/CN=www.python.org
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
 1 s:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert SHA2 Extended Validation Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA

The last CN value in the certificate chain is the name of the CA that you need to download.

For a one-off effort, do the following:

  1. Download the CRT from DigiCert
  2. Convert the CRT to PEM format
  3. Export the PIP_CERT environment variable to the path of the PEM file

(the last line assumes you are using the bash shell) before running pip.

curl -sO http://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt 
openssl x509 -inform DES -in DigiCertHighAssuranceEVRootCA.crt -out DigiCertHighAssuranceEVRootCA.pem -text
export PIP_CERT=`pwd`/DigiCertHighAssuranceEVRootCA.pem

To make this re-usable, put DigiCertHighAssuranceEVRootCA.crt somewhere common and export PIP_CERT accordingly in your ~/.bashrc.


回答 8

您可以通过以下方式解决问题CERTIFICATE_VERIFY_FAILED

  • 使用HTTP代替HTTPS(例如--index-url=http://pypi.python.org/simple/)。
  • 使用--cert <trusted.pem>CA_BUNDLE变量指定备用CA捆绑包。

    例如,您可以从Web浏览器转到失败的URL,然后将根证书导入到您的系统中。

  • 运行python -c "import ssl; print(ssl.get_default_verify_paths())"以检查当前的(验证是否存在)。

  • OpenSSL具有一对环境(SSL_CERT_DIRSSL_CERT_FILE),可用于指定不同的证书数据库PEP-476
  • 用于--trusted-host <hostname>将主机标记为可信。
  • 在Python中verify=False用于requests.get(请参阅:SSL证书验证)。
  • 使用--proxy <proxy>以避免证书检查。

有关更多信息,请参见套接字对象的TLS / SSL包装器-验证证书

You’ve the following possibilities to solve issue with CERTIFICATE_VERIFY_FAILED:

  • Use HTTP instead of HTTPS (e.g. --index-url=http://pypi.python.org/simple/).
  • Use --cert <trusted.pem> or CA_BUNDLE variable to specify alternative CA bundle.

    E.g. you can go to failing URL from web-browser and import root certificate into your system.

  • Run python -c "import ssl; print(ssl.get_default_verify_paths())" to check the current one (validate if exists).

  • OpenSSL has a pair of environments (SSL_CERT_DIR, SSL_CERT_FILE) which can be used to specify different certificate databasePEP-476.
  • Use --trusted-host <hostname> to mark the host as trusted.
  • In Python use verify=False for requests.get (see: SSL Cert Verification).
  • Use --proxy <proxy> to avoid certificate checks.

Read more at: TLS/SSL wrapper for socket objects – Verifying certificates.


回答 9

正确设置时间和日期!

对我来说,结果表明我的日期和时间在Raspberry Pi上配置错误。结果是使用https://files.pythonhosted.org/服务器,所有SSL和HTTPS连接均失败。

像这样更新它:

sudo date -s "Wed Thu  23 11:12:00 GMT+1 2018"
sudo dpkg-reconfigure tzdata

或直接以Google的时间为准:

参考:https : //superuser.com/a/635024/935136

sudo date -s "$(curl -s --head http://google.com | grep ^Date: | sed 's/Date: //g')"
sudo dpkg-reconfigure tzdata

Set Time and Date correct!

For me, it came out that my date and time was misconfigured on Raspberry Pi. The result was that all SSL and HTTPS connections failed, using the https://files.pythonhosted.org/ server.

Update it like this:

sudo date -s "Wed Thu  23 11:12:00 GMT+1 2018"
sudo dpkg-reconfigure tzdata

Or directly with e.g. Google’s time:

Ref.: https://superuser.com/a/635024/935136

sudo date -s "$(curl -s --head http://google.com | grep ^Date: | sed 's/Date: //g')"
sudo dpkg-reconfigure tzdata

回答 10

我最近遇到了这个问题,因为我公司的Web内容过滤器使用自己的证书颁发机构,以便可以过滤SSL流量。在我的情况下,PIP似乎没有使用系统的CA证书,从而产生了您提到的错误。后来将PIP降级到1.2.1版会带来一系列问题,因此我回到了Python 3.4附带的原始版本。

我的解决方法非常简单:使用easy_install。它要么不检查证书(例如旧的PIP版本),要么知道使用系统证书,因为它每次都对我有用,我仍然可以使用PIP卸载使用easy_install安装的软件包。

如果那行不通,并且您可以访问没有问题的网络或计算机,则可以始终设置自己的个人PyPI服务器:如何在没有镜像的情况下创建本地自己的pypi存储库索引?

我几乎做到了,直到我尝试将其easy_install作为最后的努力。

I recently ran into this problem because of my company’s web content filter that uses its own Certificate Authority so that it can filter SSL traffic. PIP doesn’t seem to be using the system’s CA certificates in my case, producing the error you mention. Downgrading PIP to version 1.2.1 presented its own set of problems later on, so I went back to the original version that came with Python 3.4.

My workaround is quite simple: use easy_install. Either it doesn’t check the certs (like the old PIP version), or it knows to use the system certs because it works every time for me and I can still use PIP to uninstall packages installed with easy_install.

If that doesn’t work and you can get access to a network or computer that doesn’t have the issue, you could always setup your own personal PyPI server: how to create local own pypi repository index without mirror?

I almost did that until I tried using easy_install as a last ditch effort.


回答 11

您可以尝试使用http而不是https来绕过SSL错误。当然,就安全性而言,并不是最佳选择,但是如果您急于使用它,可以采取以下措施:

pip install --index-url=http://pypi.python.org/simple/ linkchecker

You can try to bypass the SSL error by using http instead of https. Of course this is not optimal in terms of security, but if you are in a hurry it should do the trick:

pip install --index-url=http://pypi.python.org/simple/ linkchecker

回答 12

使用答案

pip install --trusted-host pypi.python.org <package>

工作。但是,您必须检查是否存在重定向或缓存pip命中。在Windows 7上pip 9.0.1,我必须运行

pip install \
  --trusted-host pypi.python.org \
  --trusted-host pypi.org \
  --trusted-host files.pythonhosted.org \
  <package>

您可以使用详细标志找到它们。

The answers to use

pip install --trusted-host pypi.python.org <package>

work. But you’ll have to check if there are redirects or caches pip is hitting. On Windows 7 with pip 9.0.1, I had to run

pip install \
  --trusted-host pypi.python.org \
  --trusted-host pypi.org \
  --trusted-host files.pythonhosted.org \
  <package>

You can find these with the verbose flag.


回答 13

我使用easy_install安装了pip 1.2.1,并升级到了最新版本的pip(当时为6.0.7),可以在我的情况下安装软件包。

easy_install pip==1.2.1
pip install --upgrade pip

I installed pip 1.2.1 with easy_install and upgraded to latest version of pip (6.0.7 at the time) which is able to install packages in my case.

easy_install pip==1.2.1
pip install --upgrade pip

回答 14

您有4个选择:

使用证书作为参数

$ pip install --cert /path/to/mycertificate.crt linkchecker

在证书中使用证书 pip.conf

创建此文件:

$HOME/.pip/pip.conf (Linux)

%HOME%\pip\pip.ini (Windows)

并添加以下行:

[global]
cert = /path/to/mycertificate.crt

忽略证书并使用HTTP

$ pip install --trusted-host pypi.python.org linkchecker

忽略证书并在pip.conf中使用HTTP

创建此文件:

$HOME/.pip/pip.conf (Linux)

%HOME%\pip\pip.ini (Windows)

并添加以下行:

[global]
trusted-host = pypi.python.org

资源

You have 4 options:

Using a certificate as parameter

$ pip install --cert /path/to/mycertificate.crt linkchecker

Using a certificate in a pip.conf

Create this file:

$HOME/.pip/pip.conf (Linux)

%HOME%\pip\pip.ini (Windows)

and add these lines:

[global]
cert = /path/to/mycertificate.crt

Ignoring certificate and using HTTP

$ pip install --trusted-host pypi.python.org linkchecker

Ignoring certificate and using HTTP in a pip.conf

Create this file:

$HOME/.pip/pip.conf (Linux)

%HOME%\pip\pip.ini (Windows)

and add these lines:

[global]
trusted-host = pypi.python.org

Source


回答 15

首先,

    pip install --trusted-host pypi.python.org <package name>

没有为我工作。我一直收到CERTIFICATE_VERIFY_FAILED错误。但是,我在错误消息中注意到它们引用了“ pypi.org”站点。因此,我将其用作受信任的主机名,而不是pypi.python.org。那几乎使我到了那里。CERTIFICATE_VERIFY_FAILED仍使加载失败,但是稍后。找到对失败网站的引用,我将其作为受信任的主机。最终对我有用的是:

    pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org <package name>

First of all,

    pip install --trusted-host pypi.python.org <package name>

did not work for me. I kept getting the CERTIFICATE_VERIFY_FAILED error. However, I noticed in the error messages that they referenced the ‘pypi.org’ site. So, I used this as the trusted host name instead of pypi.python.org. That almost got me there; the load was still failing with CERTIFICATE_VERIFY_FAILED, but at a later point. Finding the reference to the website that was failing, I included it as a trusted host. What eventually worked for me was:

    pip install --trusted-host pypi.org --trusted-host files.pythonhosted.org <package name>

回答 16

我不确定这是否相关,但是我有一个类似的问题,可以通过将这些文件从Anaconda3 / Library / bin复制到Anaconda3 / DLLs来解决:

libcrypto-1_1-x64.dll

libssl-1_1-x64.dll

I’m not sure if this is related, but I had a similar problem which was fixed by copying these files from Anaconda3/Library/bin to Anaconda3/DLLs :

libcrypto-1_1-x64.dll

libssl-1_1-x64.dll


回答 17

pip install ftputil在64位Windows 7 Enterprise上尝试使用ActivePython 2.7.8,ActivePython 3.4.1和“常规” Python 3.4.2时遇到了相同的问题。所有尝试均以与OP相同的错误失败。

通过降级为pip 1.2.1解决了Python 3.4.2的问题:(easy_install pip==1.2.1请参阅https://stackoverflow.com/a/16370731/234235)。同样的修复也适用于ActivePython 2.7.8。

该bug于2013年3月报告,目前仍在打开:https : //github.com/pypa/pip/issues/829

Had the same problem trying pip install ftputil with ActivePython 2.7.8, ActivePython 3.4.1, and “stock” Python 3.4.2 on 64-bit Windows 7 Enterprise. All attempts failed with the same errors as OP.

Worked around the problem for Python 3.4.2 by downgrading to pip 1.2.1: easy_install pip==1.2.1 (see https://stackoverflow.com/a/16370731/234235). Same fix also worked for ActivePython 2.7.8.

The bug, reported in March 2013, is still open: https://github.com/pypa/pip/issues/829.


回答 18

直到我使用–verbose选项查看它想要进入files.pythonhosted.org而不是pypi.python.org为止,此页面上的所有内容都对我没有作用:

pip install --trusted-host files.pythonhosted.org <package_name>

因此,请通过–verbose选项检查实际失败的URL。

Nothing on this page worked for me until I used the –verbose option to see that it wanted to get to files.pythonhosted.org rather than pypi.python.org:

pip install --trusted-host files.pythonhosted.org <package_name>

So check the URL that it’s actually failing on via the –verbose option.


回答 19

我通过删除我的点子并安装了较旧版本的点子来解决此问题:https : //pypi.python.org/pypi/pip/1.2.1

I solved this problem by removing my pip and installing the older version of pip: https://pypi.python.org/pypi/pip/1.2.1


回答 20

您可以尝试忽略“ https”:

pip install --index-url=http://pypi.python.org/simple/ --trusted-host pypi.python.org  [your package..]

You can try this to ignore “https”:

pip install --index-url=http://pypi.python.org/simple/ --trusted-host pypi.python.org  [your package..]

回答 21

一种解决方案(对于Windows)是pip.ini%AppData%\pip\文件夹上创建一个名为的文件(如果该文件夹不存在,则创建该文件夹)并插入以下详细信息:

[global]
cert = C:/certs/python_root.pem
proxy = http://my_user@my_company.com:my_password@proxy_ip:proxy_port

…然后我们可以执行安装指令:

pip3 install PyQt5

另一个选择是使用代理和证书的参数来安装软件包。

$ pip3 install --proxy http://my_user@my_company.com:my_password@proxy_ip:proxy_port \
   --cert C:/certs/python_root.pem PyQt5

要将证书*.cer文件转换为所需*.pem格式,请执行以下指令:

$ openssl x509 -inform der -in python_root.cer -out python_root.pem

希望这对某人有帮助!

One solution (for Windows) is to create a file called pip.ini on the %AppData%\pip\ folder (create the folder if it doesn’t exist) and insert the following details:

[global]
cert = C:/certs/python_root.pem
proxy = http://my_user@my_company.com:my_password@proxy_ip:proxy_port

…and then we can execute the install instruction:

pip3 install PyQt5

Another option is to install the package using arguments for the proxy and certificate…

$ pip3 install --proxy http://my_user@my_company.com:my_password@proxy_ip:proxy_port \
   --cert C:/certs/python_root.pem PyQt5

To convert the certificate *.cer files to the required *.pem format execute the following instruction:

$ openssl x509 -inform der -in python_root.cer -out python_root.pem

Hope this helps someone!


回答 22

就我而言,这是由于SSL证书是由公司内部CA签署的。使用类似的解决方法pip --cert无济于事,但以下软件包提供了帮助:

pip install pip_system_certs

参见:https : //pypi.org/project/pip-system-certs/

该软件包修补pip并在运行时请求使用默认系统存储中的证书(而不是捆绑的证书ca)。

这将使pip可以验证与cert的服务器之间的tls / ssl连接是否受系统安装信任。

In my case it was due to SSL certificate being signed by internal CA of my company. Using workarounds like pip --cert did not help, but the following package did:

pip install pip_system_certs

See: https://pypi.org/project/pip-system-certs/

This package patches pip and requests at runtime to use certificates from the default system store (rather than the bundled certs ca).

This will allow pip to verify tls/ssl connections to servers who’s cert is trusted by your system install.


回答 23

对我来说,这是因为以前我正在运行将代理(设置为提琴手),重新打开控制台或重新启动的脚本,以解决此问题。

for me this is because previously I’m running script which set proxy (to fiddler), reopening console or reboot fix the problem.


回答 24

最近,我在Visual Studio 2015的python 3.6中遇到了同样的问题。花了2天后,我得到了解决方案及其对我来说很好的工作。

尝试使用pip或从Visual Studio安装numpy时出现以下错误收集numpy无法获取URL https://pypi.python.org/simple/numpy/:确认ssl证书时出现问题:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败(_ssl.c:748)-跳过找不到满足numpy要求的版本(来自版本:)找不到numpy的匹配发行版

解析度 :

对于Windows操作系统

  1. 打开->“%appdata%”如果不存在,则创建“ pip”文件夹。
  2. 在pip文件夹中创建“ pip.ini”文件。
  3. 编辑文件并编写
    [global]
    trusted-host = pypi.python.org保存并关闭文件。现在使用pip / visual studio安装,效果很好。

Recently I faced the same issue in python 3.6 with visual studio 2015. After spending 2 days, I got the solution and its working fine for me.

I got below error while try to install numpy using pip or from visual studio Collecting numpy Could not fetch URL https://pypi.python.org/simple/numpy/: There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748) – skipping Could not find a version that satisfies the requirement numpy (from versions: ) No matching distribution found for numpy

Resolution :

For Windows OS

  1. open -> “%appdata%” Create “pip” folder if not exists.
  2. In pip folder create “pip.ini” file.
  3. Edit file and write
    [global]
    trusted-host = pypi.python.org Save and Close the file. Now install using pip/visual studio it works fine.

回答 25

就我而言,我在最小的高山码头工人镜像中运行Python。它缺少根CA证书。固定:

apk update && apk add ca-certificates

In my case, I was running Python in the minimal alpine docker image. It was missing root CA certificates. Fix:

apk update && apk add ca-certificates


回答 26

瓦尔斯坦回答帮助了我。

我在电脑上的任何地方都找不到pip.ini文件。以下内容也是如此。

  1. 转到AppData文件夹。您可以通过打开命令提示符并键入echo%AppData%来获取appdata文件夹。

使用命令提示的AppData位置

或者直接在Windows资源管理器中键入%AppData%。

Windows资源管理器中AppData的位置

  1. 在该appdata文件夹内创建一个名为pip的文件夹。

  2. 在您刚创建的pip文件夹中,创建一个名为pip.ini的简单文本文件。

  3. 使用您选择的简单编辑器将以下配置设置粘贴到该文件中。

pip.ini文件:

[list]
format=columns

[global]
trusted-host = pypi.python.org pypi.org

您现在应该可以进行了。

Vaulstein answer helped me.

I did not find the pip.ini file anywhere on my pc. So did the following.

  1. Went to the the AppData folder. You can get the appdata folder by opening up the command prompt and type echo %AppData%

AppData location using command prompt

Or simply type %AppData% in windows explorer.

AppData location in windows explorer

  1. Create a folder called pip inside of that appdata folder.

  2. In that pip folder that you just created, create a simple textfile called pip.ini

  3. Past the following config settings in that file using a simple editor of your choice.

pip.ini file:

[list]
format=columns

[global]
trusted-host = pypi.python.org pypi.org

You should now be good to go.


回答 27

我遇到了类似的问题。对我有用的解决方案1)卸载python 2.7 2)删除python27文件夹3)重新安装最新的python

I faced a similar issue. The solution that worked for me 1) uninstall python 2.7 2) delete python27 folder 3) reinstall the latest python


回答 28

对我而言,建议的方法都无效-使用cert,HTTP,可信主机。

在我的情况下,切换到该程序包的另一个版本是可行的(在此实例中,paho-mqtt 1.3.1代替了paho-mqtt 1.3.0)。

看起来问题是特定于该软件包版本的。

For me none of the suggested methods worked – using cert, HTTP, trusted-host.

In my case switching to a different version of the package worked (paho-mqtt 1.3.1 instead of paho-mqtt 1.3.0 in this instance).

Looks like problem was specific to that package version.


回答 29

如果您的系统中缺少某些证书,则可能会出现此问题。例如,在opensuse上安装ca-certificates-mozilla

You may have this problem if some certificates are missing in your system.eg on opensuse install ca-certificates-mozilla


确定整数是否在其他两个整数之间?

问题:确定整数是否在其他两个整数之间?

如何确定给定的整数是否在其他两个整数之间(例如,大于/等于10000和小于/等于30000)?

我正在使用2.3 IDLE,到目前为止,我一直没有尝试:

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

How do I determine whether a given integer is between two other integers (e.g. greater than/equal to 10000 and less than/equal to 30000)?

I’m using 2.3 IDLE and what I’ve attempted so far is not working:

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

回答 0

if 10000 <= number <= 30000:
    pass
if 10000 <= number <= 30000:
    pass

回答 1

>>> r = range(1, 4)
>>> 1 in r
True
>>> 2 in r
True
>>> 3 in r
True
>>> 4 in r
False
>>> 5 in r
False
>>> 0 in r
False
>>> r = range(1, 4)
>>> 1 in r
True
>>> 2 in r
True
>>> 3 in r
True
>>> 4 in r
False
>>> 5 in r
False
>>> 0 in r
False

回答 2

您的操作员不正确。应该是if number >= 10000 and number <= 30000:。此外,Python的缩写是if 10000 <= number <= 30000:

Your operator is incorrect. Should be if number >= 10000 and number <= 30000:. Additionally, Python has a shorthand for this sort of thing, if 10000 <= number <= 30000:.


回答 3

您的代码段,

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

实际检查数字是否同时大于10000和30000。

假设您要检查数字范围在10000-30000之间,可以使用Python间隔比较:

if 10000 <= number <= 30000:
    print ("you have to pay 5% taxes")

Python文档中进一步描述此Python功能。

Your code snippet,

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

actually checks if number is larger than both 10000 and 30000.

Assuming you want to check that the number is in the range 10000 – 30000, you could use the Python interval comparison:

if 10000 <= number <= 30000:
    print ("you have to pay 5% taxes")

This Python feature is further described in the Python documentation.


回答 4

if number >= 10000 and number <= 30000:
    print ("you have to pay 5% taxes")
if number >= 10000 and number <= 30000:
    print ("you have to pay 5% taxes")

回答 5

比较的麻烦在于,当您将一个>=应该放置在<=

#                             v---------- should be <
if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

Python使您可以用语言写下您的意思

if number in xrange(10000, 30001): # ok you have to remember 30000 + 1 here :)

在Python3中,您需要使用range代替xrange

编辑:人们似乎更关注微基准标记以及如何进行酷链接操作。我的答案是关于防御性(错误的攻击面更少)的编程。

由于评论中有声明,因此我在此处为Python3.5.2添加了微型基准测试

$ python3.5 -m timeit "5 in range(10000, 30000)"
1000000 loops, best of 3: 0.266 usec per loop
$ python3.5 -m timeit "10000 <= 5 < 30000"
10000000 loops, best of 3: 0.0327 usec per loop

如果您担心性能,可以一次计算范围

$ python3.5 -m timeit -s "R=range(10000, 30000)" "5 in R"
10000000 loops, best of 3: 0.0551 usec per loop

The trouble with comparisons is that they can be difficult to debug when you put a >= where there should be a <=

#                             v---------- should be <
if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

Python lets you just write what you mean in words

if number in xrange(10000, 30001): # ok you have to remember 30000 + 1 here :)

In Python3, you need to use range instead of xrange.

edit: People seem to be more concerned with microbench marks and how cool chaining operations. My answer is about defensive (less attack surface for bugs) programming.

As a result of a claim in the comments, I’ve added the micro benchmark here for Python3.5.2

$ python3.5 -m timeit "5 in range(10000, 30000)"
1000000 loops, best of 3: 0.266 usec per loop
$ python3.5 -m timeit "10000 <= 5 < 30000"
10000000 loops, best of 3: 0.0327 usec per loop

If you are worried about performance, you could compute the range once

$ python3.5 -m timeit -s "R=range(10000, 30000)" "5 in R"
10000000 loops, best of 3: 0.0551 usec per loop

回答 6

定义数字之间的范围:

r = range(1,10)

然后使用它:

if num in r:
    print("All right!")

Define the range between the numbers:

r = range(1,10)

Then use it:

if num in r:
    print("All right!")

回答 7

两种比较三个整数并检查b是否在ac之间的方法

if a < b < c:
    pass

if a < b and b < c:
    pass

第一个看起来更易读,但是第二个运行得更快

让我们使用dis.dis进行比较:

    >>> dis.dis('a < b and b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 COMPARE_OP               0 (<)
              6 JUMP_IF_FALSE_OR_POP    14
              8 LOAD_NAME                1 (b)
             10 LOAD_NAME                2 (c)
             12 COMPARE_OP               0 (<)
        >>   14 RETURN_VALUE
>>> dis.dis('a < b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               0 (<)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_NAME                2 (c)
             14 COMPARE_OP               0 (<)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE
>>>

并使用timeit

~$ python3 -m timeit "1 < 2 and 2 < 3"
10000000 loops, best of 3: 0.0366 usec per loop

~$ python3 -m timeit "1 < 2 < 3"
10000000 loops, best of 3: 0.0396 usec per loop

此外,您可以按照之前的建议使用range,但是它要慢得多。

There are two ways to compare three integers and check whether b is between a and c:

if a < b < c:
    pass

and

if a < b and b < c:
    pass

The first one looks like more readable, but the second one runs faster.

Let’s compare using dis.dis:

    >>> dis.dis('a < b and b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 COMPARE_OP               0 (<)
              6 JUMP_IF_FALSE_OR_POP    14
              8 LOAD_NAME                1 (b)
             10 LOAD_NAME                2 (c)
             12 COMPARE_OP               0 (<)
        >>   14 RETURN_VALUE
>>> dis.dis('a < b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               0 (<)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_NAME                2 (c)
             14 COMPARE_OP               0 (<)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE
>>>

and using timeit:

~$ python3 -m timeit "1 < 2 and 2 < 3"
10000000 loops, best of 3: 0.0366 usec per loop

~$ python3 -m timeit "1 < 2 < 3"
10000000 loops, best of 3: 0.0396 usec per loop

also, you may use range, as suggested before, however it is much more slower.


回答 8

假设有3个非负整数:ab,和c。从数学上讲,如果我们想确定是否c介于a和之间b,可以使用以下公式:

(c-a)*(b-c)> = 0

或在Python中:

> print((c - a) * (b - c) >= 0)
True

Suppose there are 3 non-negative integers: a, b, and c. Mathematically speaking, if we want to determine if c is between a and b, inclusively, one can use this formula:

(c – a) * (b – c) >= 0

or in Python:

> print((c - a) * (b - c) >= 0)
True

回答 9

仅当数字介于10,000和30,000之间时,您才希望输出打印给定语句。

代码应该是;

if number >= 10000 and number <= 30000:
    print("you have to pay 5% taxes")

You want the output to print the given statement if and only if the number falls between 10,000 and 30,000.

Code should be;

if number >= 10000 and number <= 30000:
    print("you have to pay 5% taxes")

回答 10

条件应该是

if number == 10000 and number <= 30000:
     print("5% tax payable")

使用的原因number == 10000是,如果number的值是50000,并且我们使用number >= 10000该条件,那么条件将过去,这不是您想要的。

The condition should be,

if number == 10000 and number <= 30000:
     print("5% tax payable")

reason for using number == 10000 is that if number’s value is 50000 and if we use number >= 10000 the condition will pass, which is not what you want.


Python:检查“字典”是否为空似乎不起作用

问题:Python:检查“字典”是否为空似乎不起作用

我正在尝试检查字典是否为空,但是行为不正常。它只是跳过它并显示“ 联机”,除了显示消息外没有任何其他内容。有什么主意吗?

 def isEmpty(self, dictionary):
   for element in dictionary:
     if element:
       return True
     return False

 def onMessage(self, socket, message):
  if self.isEmpty(self.users) == False:
     socket.send("Nobody is online, please use REGISTER command" \
                 " in order to register into the server")
  else:
     socket.send("ONLINE " + ' ' .join(self.users.keys())) 

I am trying to check if a dictionary is empty but it doesn’t behave properly. It just skips it and displays ONLINE without anything except of display the message. Any ideas why ?

 def isEmpty(self, dictionary):
   for element in dictionary:
     if element:
       return True
     return False

 def onMessage(self, socket, message):
  if self.isEmpty(self.users) == False:
     socket.send("Nobody is online, please use REGISTER command" \
                 " in order to register into the server")
  else:
     socket.send("ONLINE " + ' ' .join(self.users.keys())) 

回答 0

空字典在Python中的计算结果为False

>>> dct = {}
>>> bool(dct)
False
>>> not dct
True
>>>

因此,您的isEmpty功能是不必要的。您需要做的只是:

def onMessage(self, socket, message):
    if not self.users:
        socket.send("Nobody is online, please use REGISTER command" \
                    " in order to register into the server")
    else:
        socket.send("ONLINE " + ' ' .join(self.users.keys()))

Empty dictionaries evaluate to False in Python:

>>> dct = {}
>>> bool(dct)
False
>>> not dct
True
>>>

Thus, your isEmpty function is unnecessary. All you need to do is:

def onMessage(self, socket, message):
    if not self.users:
        socket.send("Nobody is online, please use REGISTER command" \
                    " in order to register into the server")
    else:
        socket.send("ONLINE " + ' ' .join(self.users.keys()))

回答 1

您可以通过以下三种方法检查dict是否为空。我更喜欢只使用第一种方法。其他两种方式过于罗y。

test_dict = {}

if not test_dict:
    print "Dict is Empty"


if not bool(test_dict):
    print "Dict is Empty"


if len(test_dict) == 0:
    print "Dict is Empty"

Here are three ways you can check if dict is empty. I prefer using the first way only though. The other two ways are way too wordy.

test_dict = {}

if not test_dict:
    print "Dict is Empty"


if not bool(test_dict):
    print "Dict is Empty"


if len(test_dict) == 0:
    print "Dict is Empty"

回答 2

dict = {}
print(len(dict.keys()))

如果length为零,则表示dict为空

dict = {}
print(len(dict.keys()))

if length is zero means that dict is empty


回答 3

检查空字典的简单方法如下:

        a= {}

    1. if a == {}:
           print ('empty dict')
    2. if not a:
           print ('empty dict')

尽管方法1st在a = None时更为严格,但方法1将提供正确的结果,而方法2将提供不正确的结果。

Simple ways to check an empty dict are below:

        a= {}

    1. if a == {}:
           print ('empty dict')
    2. if not a:
           print ('empty dict')

Although method 1st is more strict as when a = None, method 1 will provide correct result but method 2 will give an incorrect result.


回答 4

字典可以自动转换为布尔值,布尔值为False空字典和True非空字典。

if myDictionary: non_empty_clause()
else: empty_clause()

如果这看起来太惯用了,您还可以测试len(myDictionary)零,或测试set(myDictionary.keys())一个空集,或仅测试的相等性{}

isEmpty函数不仅是不必要的,而且您的实现还存在多个我可以发现表面现象的问题。

  1. return False语句缩进太深了一层。它应该在for循环之外,并且与该for语句处于同一级别。如此一来,您的代码将只处理一个任意选择的密钥(如果存在一个密钥)。如果键不存在,则该函数将返回None,并将其强制转换为布尔False。哎哟! 所有空字典将被归类为假阴性。
  2. 如果字典不为空,则代码将仅处理一个键,并将其值强制转换为布尔值。您甚至不能假设每次调用都对同一个键进行评估。因此会有误报。
  3. 假设您更正了return False语句的缩进并将其移出for循环。然后,您得到的是所有键的布尔值OR,或者False如果字典为空。仍然会有误报和误报。进行更正并针对以下词典进行测试以获取证据。

myDictionary={0:'zero', '':'Empty string', None:'None value', False:'Boolean False value', ():'Empty tuple'}

A dictionary can be automatically cast to boolean which evaluates to False for empty dictionary and True for non-empty dictionary.

if myDictionary: non_empty_clause()
else: empty_clause()

If this looks too idiomatic, you can also test len(myDictionary) for zero, or set(myDictionary.keys()) for an empty set, or simply test for equality with {}.

The isEmpty function is not only unnecessary but also your implementation has multiple issues that I can spot prima-facie.

  1. The return False statement is indented one level too deep. It should be outside the for loop and at the same level as the for statement. As a result, your code will process only one, arbitrarily selected key, if a key exists. If a key does not exist, the function will return None, which will be cast to boolean False. Ouch! All the empty dictionaries will be classified as false-nagatives.
  2. If the dictionary is not empty, then the code will process only one key and return its value cast to boolean. You cannot even assume that the same key is evaluated each time you call it. So there will be false positives.
  3. Let us say you correct the indentation of the return False statement and bring it outside the for loop. Then what you get is the boolean OR of all the keys, or False if the dictionary empty. Still you will have false positives and false negatives. Do the correction and test against the following dictionary for an evidence.

myDictionary={0:'zero', '':'Empty string', None:'None value', False:'Boolean False value', ():'Empty tuple'}


回答 5

您也可以使用get()。最初,我认为它只能检查密钥是否存在。

>>> d = { 'a':1, 'b':2, 'c':{}}
>>> bool(d.get('c'))
False
>>> d['c']['e']=1
>>> bool(d.get('c'))
True

我喜欢get的是它不会触发异常,因此可以轻松遍历大型结构。

You can also use get(). Initially I believed it to only check if key existed.

>>> d = { 'a':1, 'b':2, 'c':{}}
>>> bool(d.get('c'))
False
>>> d['c']['e']=1
>>> bool(d.get('c'))
True

What I like with get is that it does not trigger an exception, so it makes it easy to traverse large structures.


回答 6

为什么不使用平等测试?

def is_empty(my_dict):
    """
    Print true if given dictionary is empty
    """
    if my_dict == {}:
        print("Dict is empty !")

Why not use equality test?

def is_empty(my_dict):
    """
    Print true if given dictionary is empty
    """
    if my_dict == {}:
        print("Dict is empty !")

回答 7

使用“任何”

dict = {}

if any(dict) :

     # true
     # dictionary is not empty 

else :

     # false 
     # dictionary is empty

use ‘any’

dict = {}

if any(dict) :

     # true
     # dictionary is not empty 

else :

     # false 
     # dictionary is empty

通过整数索引选择一行熊猫系列/数据框

问题:通过整数索引选择一行熊猫系列/数据框

我很好奇,为什么df[2]不支持,而df.ix[2]df[2:3]这两个工作。

In [26]: df.ix[2]
Out[26]: 
A    1.027680
B    1.514210
C   -1.466963
D   -0.162339
Name: 2000-01-03 00:00:00

In [27]: df[2:3]
Out[27]: 
                  A        B         C         D
2000-01-03  1.02768  1.51421 -1.466963 -0.162339

我希望df[2]df[2:3]与Python索引约定一致的方式进行工作。是否有设计原因不支持按单个整数索引行?

I am curious as to why df[2] is not supported, while df.ix[2] and df[2:3] both work.

In [26]: df.ix[2]
Out[26]: 
A    1.027680
B    1.514210
C   -1.466963
D   -0.162339
Name: 2000-01-03 00:00:00

In [27]: df[2:3]
Out[27]: 
                  A        B         C         D
2000-01-03  1.02768  1.51421 -1.466963 -0.162339

I would expect df[2] to work the same way as df[2:3] to be consistent with Python indexing convention. Is there a design reason for not supporting indexing row by single integer?


回答 0

回显@HYRY,请参阅0.11中的新文档

http://pandas.pydata.org/pandas-docs/stable/indexing.html

在这里,我们有了新的运算符,.iloc以明确支持仅整数索引,并且.loc明确支持仅标签索引

例如,想象这种情况

In [1]: df = pd.DataFrame(np.random.rand(5,2),index=range(0,10,2),columns=list('AB'))

In [2]: df
Out[2]: 
          A         B
0  1.068932 -0.794307
2 -0.470056  1.192211
4 -0.284561  0.756029
6  1.037563 -0.267820
8 -0.538478 -0.800654

In [5]: df.iloc[[2]]
Out[5]: 
          A         B
4 -0.284561  0.756029

In [6]: df.loc[[2]]
Out[6]: 
          A         B
2 -0.470056  1.192211

[] 仅对行进行切片(按标签位置)

echoing @HYRY, see the new docs in 0.11

http://pandas.pydata.org/pandas-docs/stable/indexing.html

Here we have new operators, .iloc to explicity support only integer indexing, and .loc to explicity support only label indexing

e.g. imagine this scenario

In [1]: df = pd.DataFrame(np.random.rand(5,2),index=range(0,10,2),columns=list('AB'))

In [2]: df
Out[2]: 
          A         B
0  1.068932 -0.794307
2 -0.470056  1.192211
4 -0.284561  0.756029
6  1.037563 -0.267820
8 -0.538478 -0.800654

In [5]: df.iloc[[2]]
Out[5]: 
          A         B
4 -0.284561  0.756029

In [6]: df.loc[[2]]
Out[6]: 
          A         B
2 -0.470056  1.192211

[] slices the rows (by label location) only


回答 1

DataFrame索引运算符的主要目的[]是选择列。

当索引运算符传递字符串或整数时,它将尝试查找具有该特定名称的列并将其作为Series返回。

因此,在上述问题中:df[2]搜索与整数值匹配的列名2。该列不存在,并且KeyError引发a。


使用切片符号时,DataFrame索引运算符完全更改行为以选择行

奇怪的是,当给定切片时,DataFrame索引运算符选择行,并且可以按整数位置或按索引标签来选择行。

df[2:3]

这将从整数位置为2的行开始切为3,最后一个元素除外。因此,只需一行。下面的代码选择从整数位置6开始的行,直到每第三行从20开始但不包括20的行。

df[6:20:3]

如果DataFrame索引中包含字符串,则还可以使用由字符串标签组成的切片。有关更多详细信息,请参见.iloc与.loc上的此解决方案

我几乎从未将这种切片符号与索引运算符一起使用,因为它不是显式的,而且几乎从未使用过。按行切片时,请坚持使用.loc/.iloc

The primary purpose of the DataFrame indexing operator, [] is to select columns.

When the indexing operator is passed a string or integer, it attempts to find a column with that particular name and return it as a Series.

So, in the question above: df[2] searches for a column name matching the integer value 2. This column does not exist and a KeyError is raised.


The DataFrame indexing operator completely changes behavior to select rows when slice notation is used

Strangely, when given a slice, the DataFrame indexing operator selects rows and can do so by integer location or by index label.

df[2:3]

This will slice beginning from the row with integer location 2 up to 3, exclusive of the last element. So, just a single row. The following selects rows beginning at integer location 6 up to but not including 20 by every third row.

df[6:20:3]

You can also use slices consisting of string labels if your DataFrame index has strings in it. For more details, see this solution on .iloc vs .loc.

I almost never use this slice notation with the indexing operator as its not explicit and hardly ever used. When slicing by rows, stick with .loc/.iloc.


回答 2

您可以将DataFrame视为Series的字典。df[key]尝试通过选择列索引key并返回Series对象。

但是,在[]内切片会对行进行切片,因为这是非常常见的操作。

您可以阅读文档以了解详细信息:

http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics

You can think DataFrame as a dict of Series. df[key] try to select the column index by key and returns a Series object.

However slicing inside of [] slices the rows, because it’s a very common operation.

You can read the document for detail:

http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics


回答 3

要基于索引访问熊猫表,还可以考虑使用numpy.as_array选项将表转换为Numpy数组,方法如下:

np_df = df.as_matrix()

然后

np_df[i] 

会工作。

To index-based access to the pandas table, one can also consider numpy.as_array option to convert the table to Numpy array as

np_df = df.as_matrix()

and then

np_df[i] 

would work.


回答 4

您可以看一下源代码

DataFrame具有对_slice()进行切片的私有函数DataFrame,并且它允许参数axis确定要切片的轴。在__getitem__()DataFrame不设置轴,同时调用_slice()。因此_slice(),默认情况下将其切片为轴0。

您可以进行一个简单的实验,这可能对您有所帮助:

print df._slice(slice(0, 2))
print df._slice(slice(0, 2), 0)
print df._slice(slice(0, 2), 1)

You can take a look at the source code .

DataFrame has a private function _slice() to slice the DataFrame, and it allows the parameter axis to determine which axis to slice. The __getitem__() for DataFrame doesn’t set the axis while invoking _slice(). So the _slice() slice it by default axis 0.

You can take a simple experiment, that might help you:

print df._slice(slice(0, 2))
print df._slice(slice(0, 2), 0)
print df._slice(slice(0, 2), 1)

回答 5

您可以像这样遍历数据帧。

for ad in range(1,dataframe_c.size):
    print(dataframe_c.values[ad])

you can loop through the data frame like this .

for ad in range(1,dataframe_c.size):
    print(dataframe_c.values[ad])

Python中是否存在“不相等”运算符?

问题:Python中是否存在“不相等”运算符?

你怎么说不等于?

喜欢

if hi == hi:
    print "hi"
elif hi (does not equal) bye:
    print "no hi"

是否有等同于==“不平等”的东西?

How would you say does not equal?

Like

if hi == hi:
    print "hi"
elif hi (does not equal) bye:
    print "no hi"

Is there something equivalent to == that means “not equal”?


回答 0

使用!=。请参阅比较运算符。为了比较对象身份,可以使用关键字is及其否定词is not

例如

1 == 1 #  -> True
1 != 1 #  -> False
[] is [] #-> False (distinct objects)
a = b = []; a is b # -> True (same object)

Use !=. See comparison operators. For comparing object identities, you can use the keyword is and its negation is not.

e.g.

1 == 1 #  -> True
1 != 1 #  -> False
[] is [] #-> False (distinct objects)
a = b = []; a is b # -> True (same object)

回答 1

不等于 != (vs等于==

您是否在问这样的事情?

answer = 'hi'

if answer == 'hi':     # equal
   print "hi"
elif answer != 'hi':   # not equal
   print "no hi"

Python-基本运算符图表可能会有所帮助。

Not equal != (vs equal ==)

Are you asking about something like this?

answer = 'hi'

if answer == 'hi':     # equal
   print "hi"
elif answer != 'hi':   # not equal
   print "no hi"

This Python – Basic Operators chart might be helpful.


回答 2

当两个值不同时,有一个!=(不相等)运算符返回True,尽管要小心类型,因为"1" != 1"1" == 1由于类型不同,它将始终返回True,并且始终返回False。Python是动态的但是强类型的,而其他静态类型的语言会抱怨比较不同的类型。

还有else子句:

# This will always print either "hi" or "no hi" unless something unforeseen happens.
if hi == "hi":     # The variable hi is being compared to the string "hi", strings are immutable in Python, so you could use the 'is' operator.
    print "hi"     # If indeed it is the string "hi" then print "hi"
else:              # hi and "hi" are not the same
    print "no hi"

is运算符是对象标识运算符,用于检查两个对象实际上是否相同:

a = [1, 2]
b = [1, 2]
print a == b # This will print True since they have the same values
print a is b # This will print False since they are different objects.

There’s the != (not equal) operator that returns True when two values differ, though be careful with the types because "1" != 1. This will always return True and "1" == 1 will always return False, since the types differ. Python is dynamically, but strongly typed, and other statically typed languages would complain about comparing different types.

There’s also the else clause:

# This will always print either "hi" or "no hi" unless something unforeseen happens.
if hi == "hi":     # The variable hi is being compared to the string "hi", strings are immutable in Python, so you could use the 'is' operator.
    print "hi"     # If indeed it is the string "hi" then print "hi"
else:              # hi and "hi" are not the same
    print "no hi"

The is operator is the object identity operator used to check if two objects in fact are the same:

a = [1, 2]
b = [1, 2]
print a == b # This will print True since they have the same values
print a is b # This will print False since they are different objects.

回答 3

您可以同时使用!=<>

但是,请注意,不建议!=<>不推荐的地方使用它。

You can use both != or <>.

However, note that != is preferred where <> is deprecated.


回答 4

看到其他所有人都已经列出了大多数其他方式来表示不平等,我将添加:

if not (1) == (1): # This will eval true then false
    # (ie: 1 == 1 is true but the opposite(not) is false)
    print "the world is ending" # This will only run on a if true
elif (1+1) != (2): #second if
    print "the world is ending"
    # This will only run if the first if is false and the second if is true
else: # this will only run if the if both if's are false
    print "you are good for another day"

在这种情况下,很容易将正==(true)的检查切换为负,反之亦然…

Seeing as everyone else has already listed most of the other ways to say not equal I will just add:

if not (1) == (1): # This will eval true then false
    # (ie: 1 == 1 is true but the opposite(not) is false)
    print "the world is ending" # This will only run on a if true
elif (1+1) != (2): #second if
    print "the world is ending"
    # This will only run if the first if is false and the second if is true
else: # this will only run if the if both if's are false
    print "you are good for another day"

in this case it is simple switching the check of positive == (true) to negative and vise versa…


回答 5

您可以将“不等于”用于“不等于”或“!=“。请参见以下示例:

a = 2
if a == 2:
   print("true")
else:
   print("false")

上面的代码将在“ if”条件之前将“ true”打印为a = 2。现在,请参见下面的“不等于”代码

a = 2
if a is not 3:
   print("not equal")
else:
   print("equal")

上面的代码将打印“不等于”,即早先分配的a = 2。

You can use “is not” for “not equal” or “!=”. Please see the example below:

a = 2
if a == 2:
   print("true")
else:
   print("false")

The above code will print “true” as a = 2 assigned before the “if” condition. Now please see the code below for “not equal”

a = 2
if a is not 3:
   print("not equal")
else:
   print("equal")

The above code will print “not equal” as a = 2 as assigned earlier.


回答 6

Python中有两个用于“不相等”条件的运算符-

a。)!=如果两个操作数的值不相等,则条件变为true。(a!= b)是正确的。

b。)<>如果两个操作数的值不相等,则条件变为true。(a <> b)是正确的。这类似于!=运算符。

There are two operators in Python for the “not equal” condition –

a.) != If values of the two operands are not equal, then the condition becomes true. (a != b) is true.

b.) <> If values of the two operands are not equal, then the condition becomes true. (a <> b) is true. This is similar to the != operator.


回答 7

使用!=<>。两者代表不平等。

比较运算符<>!=是相同运算符的替代拼写。!=是首选拼写;<>是过时的。[参考:Python语言参考]

Use != or <>. Both stands for not equal.

The comparison operators <> and != are alternate spellings of the same operator. != is the preferred spelling; <> is obsolescent. [Reference: Python language reference]


回答 8

您可以简单地执行以下操作:

if hi == hi:
    print "hi"
elif hi != bye:
     print "no hi"

You can simply do:

if hi == hi:
    print "hi"
elif hi != bye:
     print "no hi"

Python和JavaScript之间的JSON日期时间

问题:Python和JavaScript之间的JSON日期时间

我想使用JSON从Python发送序列化形式的datetime.datetime对象,并使用JSON在JavaScript中反序列化。做这个的最好方式是什么?

I want to send a datetime.datetime object in serialized form from Python using JSON and de-serialize in JavaScript using JSON. What is the best way to do this?


回答 0

您可以在json.dumps中添加“默认”参数来处理此问题:

date_handler = lambda obj: (
    obj.isoformat()
    if isinstance(obj, (datetime.datetime, datetime.date))
    else None
)
json.dumps(datetime.datetime.now(), default=date_handler)
'"2010-04-20T20:08:21.634121"'

这是ISO 8601格式。

更全面的默认处理程序功能:

def handler(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    elif isinstance(obj, ...):
        return ...
    else:
        raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))

更新:添加了类型和值的输出。
更新:还处理日期

You can add the ‘default’ parameter to json.dumps to handle this:

date_handler = lambda obj: (
    obj.isoformat()
    if isinstance(obj, (datetime.datetime, datetime.date))
    else None
)
json.dumps(datetime.datetime.now(), default=date_handler)
'"2010-04-20T20:08:21.634121"'

Which is ISO 8601 format.

A more comprehensive default handler function:

def handler(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    elif isinstance(obj, ...):
        return ...
    else:
        raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))

Update: Added output of type as well as value.
Update: Also handle date


回答 1

对于跨语言项目,我发现包含RfC 3339日期的字符串是最好的选择。RfC 3339日期如下所示:

  1985-04-12T23:20:50.52Z

我认为大多数格式都是显而易见的。唯一有点不寻常的事情可能是结尾处的“ Z”。它代表GMT / UTC。您还可以为CEST添加夏令时偏移,例如+02:00(德国夏季)。我个人更喜欢将所有内容保留在UTC中,直到显示为止。

为了显示,比较和存储,您可以将其保留为所有语言的字符串格式。如果您需要日期进行计算,可以轻松将其转换为大多数语言的原始日期对象。

因此,生成这样的JSON:

  json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))

不幸的是,Javascript的Date构造函数不接受RfC 3339字符串,但是Internet上有很多解析器

huTools.hujson会尝试处理Python代码中可能遇到的最常见的编码问题,包括日期/日期时间对象,同时正确处理时区。

For cross-language projects, I found out that strings containing RfC 3339 dates are the best way to go. An RfC 3339 date looks like this:

  1985-04-12T23:20:50.52Z

I think most of the format is obvious. The only somewhat unusual thing may be the “Z” at the end. It stands for GMT/UTC. You could also add a timezone offset like +02:00 for CEST (Germany in summer). I personally prefer to keep everything in UTC until it is displayed.

For displaying, comparisons and storage you can leave it in string format across all languages. If you need the date for calculations easy to convert it back to a native date object in most language.

So generate the JSON like this:

  json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))

Unfortunately, Javascript’s Date constructor doesn’t accept RfC 3339 strings but there are many parsers available on the Internet.

huTools.hujson tries to handle the most common encoding issues you might come across in Python code including date/datetime objects while handling timezones correctly.


回答 2

我已经解决了。

假设您有一个使用datetime.now()创建的Python datetime对象d。其值为:

datetime.datetime(2011, 5, 25, 13, 34, 5, 787000)

您可以将其序列化为JSON作为ISO 8601日期时间字符串:

import json    
json.dumps(d.isoformat())

日期时间对象示例将序列化为:

'"2011-05-25T13:34:05.787000"'

一旦在Javascript层中收到此值,就可以构造一个Date对象:

var d = new Date("2011-05-25T13:34:05.787000");

从Javascript 1.8.5开始,Date对象具有toJSON方法,该方法返回标准格式的字符串。要将上述Javascript对象序列化回JSON,命令将是:

d.toJSON()

这会给你:

'2011-05-25T20:34:05.787Z'

一旦在Python中收到此字符串,就可以将其反序列化为datetime对象:

datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')

这将导致以下日期时间对象,该对象与您开始时使用的对象相同,因此是正确的:

datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)

I’ve worked it out.

Let’s say you have a Python datetime object, d, created with datetime.now(). Its value is:

datetime.datetime(2011, 5, 25, 13, 34, 5, 787000)

You can serialize it to JSON as an ISO 8601 datetime string:

import json    
json.dumps(d.isoformat())

The example datetime object would be serialized as:

'"2011-05-25T13:34:05.787000"'

This value, once received in the Javascript layer, can construct a Date object:

var d = new Date("2011-05-25T13:34:05.787000");

As of Javascript 1.8.5, Date objects have a toJSON method, which returns a string in a standard format. To serialize the above Javascript object back to JSON, therefore, the command would be:

d.toJSON()

Which would give you:

'2011-05-25T20:34:05.787Z'

This string, once received in Python, could be deserialized back to a datetime object:

datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')

This results in the following datetime object, which is the same one you started with and therefore correct:

datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)

回答 3

使用json,您可以子类化JSONEncoder并重写default()方法以提供自己的自定义序列化程序:

import json
import datetime

class DateTimeJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.isoformat()
        else:
            return super(DateTimeJSONEncoder, self).default(obj)

然后,您可以这样称呼它:

>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'

Using json, you can subclass JSONEncoder and override the default() method to provide your own custom serializers:

import json
import datetime

class DateTimeJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.isoformat()
        else:
            return super(DateTimeJSONEncoder, self).default(obj)

Then, you can call it like this:

>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'

回答 4

这是一个使用标准库json模块递归编码和解码datetime.datetime和datetime.date对象的完整解决方案。此后需要Python> = 2.6,因为从那时起%f仅支持datetime.datetime.strptime()格式字符串中的格式代码。对于Python 2.5支持,%f在尝试转换之前,请从ISO日期字符串中删除和除去微秒,但是,您当然会降低微秒的精度。为了与其他来源的ISO日期字符串互操作,其中可能包括时区名称或UTC偏移量,您可能还需要在转换之前剥离日期字符串的某些部分。有关ISO日期字符串(和许多其他日期格式)的完整解析器,请参见第三方dateutil模块。

仅当ISO日期字符串是JavaScript文字对象表示法中的值或对象中嵌套结构中的值时,才起作用。作为顶级数组项目的ISO日期字符串将不会被解码。

即这有效:

date = datetime.datetime.now()
>>> json = dumps(dict(foo='bar', innerdict=dict(date=date)))
>>> json
'{"innerdict": {"date": "2010-07-15T13:16:38.365579"}, "foo": "bar"}'
>>> loads(json)
{u'innerdict': {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)},
u'foo': u'bar'}

这也是:

>>> json = dumps(['foo', 'bar', dict(date=date)])
>>> json
'["foo", "bar", {"date": "2010-07-15T13:16:38.365579"}]'
>>> loads(json)
[u'foo', u'bar', {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)}]

但这不能按预期工作:

>>> json = dumps(['foo', 'bar', date])
>>> json
'["foo", "bar", "2010-07-15T13:16:38.365579"]'
>>> loads(json)
[u'foo', u'bar', u'2010-07-15T13:16:38.365579']

这是代码:

__all__ = ['dumps', 'loads']

import datetime

try:
    import json
except ImportError:
    import simplejson as json

class JSONDateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return obj.isoformat()
        else:
            return json.JSONEncoder.default(self, obj)

def datetime_decoder(d):
    if isinstance(d, list):
        pairs = enumerate(d)
    elif isinstance(d, dict):
        pairs = d.items()
    result = []
    for k,v in pairs:
        if isinstance(v, basestring):
            try:
                # The %f format code is only supported in Python >= 2.6.
                # For Python <= 2.5 strip off microseconds
                # v = datetime.datetime.strptime(v.rsplit('.', 1)[0],
                #     '%Y-%m-%dT%H:%M:%S')
                v = datetime.datetime.strptime(v, '%Y-%m-%dT%H:%M:%S.%f')
            except ValueError:
                try:
                    v = datetime.datetime.strptime(v, '%Y-%m-%d').date()
                except ValueError:
                    pass
        elif isinstance(v, (dict, list)):
            v = datetime_decoder(v)
        result.append((k, v))
    if isinstance(d, list):
        return [x[1] for x in result]
    elif isinstance(d, dict):
        return dict(result)

def dumps(obj):
    return json.dumps(obj, cls=JSONDateTimeEncoder)

def loads(obj):
    return json.loads(obj, object_hook=datetime_decoder)

if __name__ == '__main__':
    mytimestamp = datetime.datetime.utcnow()
    mydate = datetime.date.today()
    data = dict(
        foo = 42,
        bar = [mytimestamp, mydate],
        date = mydate,
        timestamp = mytimestamp,
        struct = dict(
            date2 = mydate,
            timestamp2 = mytimestamp
        )
    )

    print repr(data)
    jsonstring = dumps(data)
    print jsonstring
    print repr(loads(jsonstring))

Here’s a fairly complete solution for recursively encoding and decoding datetime.datetime and datetime.date objects using the standard library json module. This needs Python >= 2.6 since the %f format code in the datetime.datetime.strptime() format string is only supported in since then. For Python 2.5 support, drop the %f and strip the microseconds from the ISO date string before trying to convert it, but you’ll loose microseconds precision, of course. For interoperability with ISO date strings from other sources, which may include a time zone name or UTC offset, you may also need to strip some parts of the date string before the conversion. For a complete parser for ISO date strings (and many other date formats) see the third-party dateutil module.

Decoding only works when the ISO date strings are values in a JavaScript literal object notation or in nested structures within an object. ISO date strings, which are items of a top-level array will not be decoded.

I.e. this works:

date = datetime.datetime.now()
>>> json = dumps(dict(foo='bar', innerdict=dict(date=date)))
>>> json
'{"innerdict": {"date": "2010-07-15T13:16:38.365579"}, "foo": "bar"}'
>>> loads(json)
{u'innerdict': {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)},
u'foo': u'bar'}

And this too:

>>> json = dumps(['foo', 'bar', dict(date=date)])
>>> json
'["foo", "bar", {"date": "2010-07-15T13:16:38.365579"}]'
>>> loads(json)
[u'foo', u'bar', {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)}]

But this doesn’t work as expected:

>>> json = dumps(['foo', 'bar', date])
>>> json
'["foo", "bar", "2010-07-15T13:16:38.365579"]'
>>> loads(json)
[u'foo', u'bar', u'2010-07-15T13:16:38.365579']

Here’s the code:

__all__ = ['dumps', 'loads']

import datetime

try:
    import json
except ImportError:
    import simplejson as json

class JSONDateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return obj.isoformat()
        else:
            return json.JSONEncoder.default(self, obj)

def datetime_decoder(d):
    if isinstance(d, list):
        pairs = enumerate(d)
    elif isinstance(d, dict):
        pairs = d.items()
    result = []
    for k,v in pairs:
        if isinstance(v, basestring):
            try:
                # The %f format code is only supported in Python >= 2.6.
                # For Python <= 2.5 strip off microseconds
                # v = datetime.datetime.strptime(v.rsplit('.', 1)[0],
                #     '%Y-%m-%dT%H:%M:%S')
                v = datetime.datetime.strptime(v, '%Y-%m-%dT%H:%M:%S.%f')
            except ValueError:
                try:
                    v = datetime.datetime.strptime(v, '%Y-%m-%d').date()
                except ValueError:
                    pass
        elif isinstance(v, (dict, list)):
            v = datetime_decoder(v)
        result.append((k, v))
    if isinstance(d, list):
        return [x[1] for x in result]
    elif isinstance(d, dict):
        return dict(result)

def dumps(obj):
    return json.dumps(obj, cls=JSONDateTimeEncoder)

def loads(obj):
    return json.loads(obj, object_hook=datetime_decoder)

if __name__ == '__main__':
    mytimestamp = datetime.datetime.utcnow()
    mydate = datetime.date.today()
    data = dict(
        foo = 42,
        bar = [mytimestamp, mydate],
        date = mydate,
        timestamp = mytimestamp,
        struct = dict(
            date2 = mydate,
            timestamp2 = mytimestamp
        )
    )

    print repr(data)
    jsonstring = dumps(data)
    print jsonstring
    print repr(loads(jsonstring))

回答 5

如果您确定只有Javascript将使用JSON,则我更喜欢Date直接传递Javascript 对象。

对象ctime()上的方法datetime将返回Javascript Date对象可以理解的字符串。

import datetime
date = datetime.datetime.today()
json = '{"mydate":new Date("%s")}' % date.ctime()

Javascript将很乐意将其用作对象文字,并且您已经内置了Date对象。

If you’re certain that only Javascript will be consuming the JSON, I prefer to pass Javascript Date objects directly.

The ctime() method on datetime objects will return a string that the Javascript Date object can understand.

import datetime
date = datetime.datetime.today()
json = '{"mydate":new Date("%s")}' % date.ctime()

Javascript will happily use that as an object literal, and you’ve got your Date object built right in.


回答 6

比赛后期… :)

一个非常简单的解决方案是修补json模块的默认值。例如:

import json
import datetime

json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

现在,您可以使用json.dumps(),就好像它一直支持日期时间一样。

json.dumps({'created':datetime.datetime.now()})

如果您需要始终对json模块进行此扩展,并且希望不更改您或其他人使用json序列化的方式(无论是否使用现有代码),则这是有道理的。

请注意,有些人可能认为以这种方式对库进行修补是不好的做法。如果您可能希望以多种方式扩展应用程序,则需要格外小心-在这种情况下,我建议使用ramen或JT解决方案,并在每种情况下选择合适的json扩展名。

Late in the game… :)

A very simple solution is to patch the json module default. For example:

import json
import datetime

json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

Now, you can use json.dumps() as if it had always supported datetime…

json.dumps({'created':datetime.datetime.now()})

This makes sense if you require this extension to the json module to always kick in and wish to not change the way you or others use json serialization (either in existing code or not).

Note that some may consider patching libraries in that way as bad practice. Special care need to be taken in case you may wish to extend your application in more than one way – is such a case, I suggest to use the solution by ramen or JT and choose the proper json extension in each case.


回答 7

除了时间戳,没有什么可添加到社区Wiki答案中了!

Javascript使用以下格式:

new Date().toJSON() // "2016-01-08T19:00:00.123Z"

Python端(有关json.dumps处理程序,请参见其他答案):

>>> from datetime import datetime
>>> d = datetime.strptime('2016-01-08T19:00:00.123Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> d
datetime.datetime(2016, 1, 8, 19, 0, 0, 123000)
>>> d.isoformat() + 'Z'
'2016-01-08T19:00:00.123000Z'

如果将Z保留在外,那么诸如angular的前端框架将无法在浏览器本地时区中显示日期:

> $filter('date')('2016-01-08T19:00:00.123000Z', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 20:00:00"
> $filter('date')('2016-01-08T19:00:00.123000', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 19:00:00"

Not much to add to the community wiki answer, except for timestamp!

Javascript uses the following format:

new Date().toJSON() // "2016-01-08T19:00:00.123Z"

Python side (for the json.dumps handler, see the other answers):

>>> from datetime import datetime
>>> d = datetime.strptime('2016-01-08T19:00:00.123Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> d
datetime.datetime(2016, 1, 8, 19, 0, 0, 123000)
>>> d.isoformat() + 'Z'
'2016-01-08T19:00:00.123000Z'

If you leave that Z out, frontend frameworks like angular can not display the date in browser-local timezone:

> $filter('date')('2016-01-08T19:00:00.123000Z', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 20:00:00"
> $filter('date')('2016-01-08T19:00:00.123000', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 19:00:00"

回答 8

在python方面:

import time, json
from datetime import datetime as dt
your_date = dt.now()
data = json.dumps(time.mktime(your_date.timetuple())*1000)
return data # data send to javascript

在JavaScript方面:

var your_date = new Date(data)

数据来自python的地方

On python side:

import time, json
from datetime import datetime as dt
your_date = dt.now()
data = json.dumps(time.mktime(your_date.timetuple())*1000)
return data # data send to javascript

On javascript side:

var your_date = new Date(data)

where data is result from python


回答 9

我的建议是使用一个库。pypi.org上有几个可用的。

我使用这个,它很好用:https : //pypi.python.org/pypi/asjson

My advice is to use a library. There are several available at pypi.org.

I use this one, it it works good: https://pypi.python.org/pypi/asjson


回答 10

显然,“正确的” JSON(很好的JavaScript)日期格式是2012-04-23T18:25:43.511Z-UTC和“ Z”。如果没有此功能,则从字符串创建Date()对象时,JavaScript将使用Web浏览器的本地时区。

对于“天真的”时间(Python称没有时区的时间,并且假定是本地时间),以下内容将强制使用本地时区,以便随后可以将其正确转换为UTC:

def default(obj):
    if hasattr(obj, "json") and callable(getattr(obj, "json")):
        return obj.json()
    if hasattr(obj, "isoformat") and callable(getattr(obj, "isoformat")):
        # date/time objects
        if not obj.utcoffset():
            # add local timezone to "naive" local time
            # /programming/2720319/python-figure-out-local-timezone
            tzinfo = datetime.now(timezone.utc).astimezone().tzinfo
            obj = obj.replace(tzinfo=tzinfo)
        # convert to UTC
        obj = obj.astimezone(timezone.utc)
        # strip the UTC offset
        obj = obj.replace(tzinfo=None)
        return obj.isoformat() + "Z"
    elif hasattr(obj, "__str__") and callable(getattr(obj, "__str__")):
        return str(obj)
    else:
        print("obj:", obj)
        raise TypeError(obj)

def dump(j, io):
    json.dump(j, io, indent=2, default=default)

为什么这么难。

Apparently The “right” JSON (well JavaScript) date format is 2012-04-23T18:25:43.511Z – UTC and “Z”. Without this JavaScript will use the web browser’s local timezone when creating a Date() object from the string.

For a “naive” time (what Python calls a time with no timezone and this assumes is local) the below will force local timezone so that it can then be correctly converted to UTC:

def default(obj):
    if hasattr(obj, "json") and callable(getattr(obj, "json")):
        return obj.json()
    if hasattr(obj, "isoformat") and callable(getattr(obj, "isoformat")):
        # date/time objects
        if not obj.utcoffset():
            # add local timezone to "naive" local time
            # https://stackoverflow.com/questions/2720319/python-figure-out-local-timezone
            tzinfo = datetime.now(timezone.utc).astimezone().tzinfo
            obj = obj.replace(tzinfo=tzinfo)
        # convert to UTC
        obj = obj.astimezone(timezone.utc)
        # strip the UTC offset
        obj = obj.replace(tzinfo=None)
        return obj.isoformat() + "Z"
    elif hasattr(obj, "__str__") and callable(getattr(obj, "__str__")):
        return str(obj)
    else:
        print("obj:", obj)
        raise TypeError(obj)

def dump(j, io):
    json.dump(j, io, indent=2, default=default)

why is this so hard.


回答 11

对于从Python到JavaScript的日期转换,日期对象必须采用特定的ISO格式,即ISO格式或UNIX数字。如果ISO格式缺少某些信息,则可以先使用Date.parse转换为Unix数字。此外,Date.parse也可以与React一起使用,而新的Date可能会触发异常。

如果您有一个不带毫秒的DateTime对象,则需要考虑以下因素。:

  var unixDate = Date.parse('2016-01-08T19:00:00') 
  var desiredDate = new Date(unixDate).toLocaleDateString();

在API调用之后,示例日期也可以是result.data对象中的变量。

有关以所需格式显示日期的选项(例如,显示较长的工作日),请查看MDN文档

For the Python to JavaScript date conversion, the date object needs to be in specific ISO format, i.e. ISO format or UNIX number. If the ISO format lacks some info, then you can convert to the Unix number with Date.parse first. Moreover, Date.parse works with React as well while new Date might trigger an exception.

In case you have a DateTime object without milliseconds, the following needs to be considered. :

  var unixDate = Date.parse('2016-01-08T19:00:00') 
  var desiredDate = new Date(unixDate).toLocaleDateString();

The example date could equally be a variable in the result.data object after an API call.

For options to display the date in the desired format (e.g. to display long weekdays) check out the MDN doc.


如何使用pass语句?

问题:如何使用pass语句?

我正在学习Python,并且已经到达有关该pass语句的部分。我正在使用的指南将其定义Null为通常用作占位符的语句。

我仍然不完全明白那是什么意思。有人可以告诉我一个简单/基本的情况下使用该pass语句以及为什么需要该语句吗?

I am in the process of learning Python and I have reached the section about the pass statement. The guide I’m using defines it as being a Null statement that is commonly used as a placeholder.

I still don’t fully understand what that means though. Can someone show me a simple/basic situation where the pass statement would be used and why it is needed?


回答 0

假设您正在使用尚未实现的某些方法设计一个新类。

class MyClass(object):
    def meth_a(self):
        pass

    def meth_b(self):
        print "I'm meth_b"

如果您不使用pass,则代码将无法运行。

然后,您将获得:

IndentationError: expected an indented block

总而言之,该pass语句没有什么特别的,但是可以充当占位符,如此处所示。

Suppose you are designing a new class with some methods that you don’t want to implement, yet.

class MyClass(object):
    def meth_a(self):
        pass

    def meth_b(self):
        print "I'm meth_b"

If you were to leave out the pass, the code wouldn’t run.

You would then get an:

IndentationError: expected an indented block

To summarize, the pass statement does nothing particular, but it can act as a placeholder, as demonstrated here.


回答 1

Python有句法的要求,即代码块(后ifexceptdefclass等等)不能为空。但是,空代码块在各种不同的上下文中都很有用,例如下面的示例,这是我见过的最常见的用例。

因此,如果在代码块中什么也不会发生,pass则需要a 来使该块不产生IndentationError。或者,可以使用任何语句(仅包括要求值的术语,如Ellipsis文字...或字符串,通常是文档字符串),但要说明的pass是,实际上不应该发生任何事情,不需要实际求值,并且(至少暂时)存储在内存中。

  • 忽略(全部或)某种类型的Exception(例如来自xml):

    try:
        self.version = "Expat %d.%d.%d" % expat.version_info
    except AttributeError:
        pass # unknown
    

    注意:忽略所有类型的加薪,如下面的示例中所示pandas,通常被认为是不好的做法,因为它还会捕获可能应该传递给调用者的异常,例如KeyboardInterruptor SystemExit(或HardwareIsOnFireError– 甚至您如何知道自己不是在定义了特定错误的自定义框上运行,某些调用应用程序可能想知道这些错误?)。

    try:
        os.unlink(filename_larry)
    except:
        pass
    

    替代地,至少except Error:或在这种情况下优选地except OSError:被认为是更好的实践。快速分析我安装的所有python模块后,我发现所有except ...: pass语句中有10%以上会捕获所有异常,因此在python编程中它仍然是常见的模式。

  • 派生不会添加新行为的异常类(例如scipy):

    class CompileError(Exception):
        pass
    

    同样,用作抽象基类的类通常具有显式的空值__init__或子类应该派生的其他方法。(例如pebl

    class _BaseSubmittingController(_BaseController):
        def submit(self, tasks): pass
        def retrieve(self, deferred_results): pass
    
  • 测试该代码可以针对一些测试值正确运行,而无需关心结果(来自mpmath):

    for x, error in MDNewton(mp, f, (1,-2), verbose=0,
                             norm=lambda x: norm(x, inf)):
        pass
    
  • 在类或函数定义中,通常已经有一个文档字符串,作为强制性语句要作为块中唯一的内容执行。在这种情况下,该块可能包含pass 文档字符串之外的其他内容,以便说“这确实是无所事事。”,例如pebl

    class ParsingError(Exception): 
        """Error encountered while parsing an ill-formed datafile."""
        pass
    
  • 在某些情况下,pass用作占位符时说“此方法/类/ if-block / …尚未实现,但这将是执行此操作的地方”,尽管我个人更喜欢该Ellipsis文字...,以便在前面的示例中,请严格区分此内容和故意的“无操作”。(请注意,省略号文字仅在Python 3中才是有效的表达式。
    例如,如果我用粗笔写出一个模型,我可能会写

    def update_agent(agent):
        ... 
    

    其他人可能有的地方

    def update_agent(agent):
        pass
    

    之前

    def time_step(agents):
        for agent in agents:
            update_agent(agent)
    

    提醒您update_agent稍后再填写该功能,但已经运行了一些测试以查看其余代码是否按预期运行。(这种情况的第三个选项是raise NotImplementedError。这在两种情况下特别有用:“每个子类都应实现此抽象方法,在此基类中没有定义它的通用方法”,或“此函数具有此名称尚未在此版本中实现,但这是其签名将显示为的样子”

Python has the syntactical requirement that code blocks (after if, except, def, class etc.) cannot be empty. Empty code blocks are however useful in a variety of different contexts, such as in examples below, which are the most frequent use cases I have seen.

Therefore, if nothing is supposed to happen in a code block, a pass is needed for such a block to not produce an IndentationError. Alternatively, any statement (including just a term to be evaluated, like the Ellipsis literal ... or a string, most often a docstring) can be used, but the pass makes clear that indeed nothing is supposed to happen, and does not need to be actually evaluated and (at least temporarily) stored in memory.

  • Ignoring (all or) a certain type of Exception (example from xml):

    try:
        self.version = "Expat %d.%d.%d" % expat.version_info
    except AttributeError:
        pass # unknown
    

    Note: Ignoring all types of raises, as in the following example from pandas, is generally considered bad practice, because it also catches exceptions that should probably be passed on to the caller, e.g. KeyboardInterrupt or SystemExit (or even HardwareIsOnFireError – How do you know you aren’t running on a custom box with specific errors defined, which some calling application would want to know about?).

    try:
        os.unlink(filename_larry)
    except:
        pass
    

    Instead using at least except Error: or in this case preferably except OSError: is considered much better practice. A quick analysis of all python modules I have installed gave me that more than 10% of all except ...: pass statements catch all exceptions, so it’s still a frequent pattern in python programming.

  • Deriving an exception class that does not add new behaviour (e.g. in scipy):

    class CompileError(Exception):
        pass
    

    Similarly, classes intended as abstract base class often have an explicit empty __init__ or other methods that subclasses are supposed to derive. (e.g. pebl)

    class _BaseSubmittingController(_BaseController):
        def submit(self, tasks): pass
        def retrieve(self, deferred_results): pass
    
  • Testing that code runs properly for a few test values, without caring about the results (from mpmath):

    for x, error in MDNewton(mp, f, (1,-2), verbose=0,
                             norm=lambda x: norm(x, inf)):
        pass
    
  • In class or function definitions, often a docstring is already in place as the obligatory statement to be executed as the only thing in the block. In such cases, the block may contain pass in addition to the docstring in order to say “This is indeed intended to do nothing.”, for example in pebl:

    class ParsingError(Exception): 
        """Error encountered while parsing an ill-formed datafile."""
        pass
    
  • In some cases, pass is used as a placeholder to say “This method/class/if-block/… has not been implemented yet, but this will be the place to do it”, although I personally prefer the Ellipsis literal ... in order to strictly differentiate between this and the intentional “no-op” in the previous example. (Note that the Ellipsis literal is a valid expression only in Python 3)
    For example, if I write a model in broad strokes, I might write

    def update_agent(agent):
        ... 
    

    where others might have

    def update_agent(agent):
        pass
    

    before

    def time_step(agents):
        for agent in agents:
            update_agent(agent)
    

    as a reminder to fill in the update_agent function at a later point, but run some tests already to see if the rest of the code behaves as intended. (A third option for this case is raise NotImplementedError. This is useful in particular for two cases: Either “This abstract method should be implemented by every subclass, there is no generic way to define it in this base class”, or “This function, with this name, is not yet implemented in this release, but this is what its signature will look like”)


回答 2

除了将其用作未实现函数的占位符外,它pass还可用于填充if-else语句(“显式优于隐式。”)

def some_silly_transform(n):
    # Even numbers should be divided by 2
    if n % 2 == 0:
        n /= 2
        flag = True
    # Negative odd numbers should return their absolute value
    elif n < 0:
        n = -n
        flag = True
    # Otherwise, number should remain unchanged
    else:
        pass

当然,在这种情况下,可能会使用return而不是分配,但是在需要突变的情况下,这种方法效果最佳。

使用passhere对警告将来的维护者(包括您自己!)不要在条件语句之外放置多余的步骤特别有用。在上面的示例中,flag在两个具体提到的情况下设置了,但在else-case中没有设置。如果不使用pass,将来的程序员可能会转移flag = True到该条件之外,因此flag所有情况下都应如此。


另一种情况是通常在文件底部看到样板函数:

if __name__ == "__main__":
    pass

在某些文件中,最好保留其中的内容pass,以便以后进行更轻松的编辑,并明确表明在单独运行文件时不会发生任何事情。


最后,如其他答案中所述,捕获异常时不执行任何操作可能很有用:

try:
    n[i] = 0
except IndexError:
    pass

Besides its use as a placeholder for unimplemented functions, pass can be useful in filling out an if-else statement (“Explicit is better than implicit.”)

def some_silly_transform(n):
    # Even numbers should be divided by 2
    if n % 2 == 0:
        n /= 2
        flag = True
    # Negative odd numbers should return their absolute value
    elif n < 0:
        n = -n
        flag = True
    # Otherwise, number should remain unchanged
    else:
        pass

Of course, in this case, one would probably use return instead of assignment, but in cases where mutation is desired, this works best.

The use of pass here is especially useful to warn future maintainers (including yourself!) not to put redundant steps outside of the conditional statements. In the example above, flag is set in the two specifically mentioned cases, but not in the else-case. Without using pass, a future programmer might move flag = True to outside the condition—thus setting flag in all cases.


Another case is with the boilerplate function often seen at the bottom of a file:

if __name__ == "__main__":
    pass

In some files, it might be nice to leave that there with pass to allow for easier editing later, and to make explicit that nothing is expected to happen when the file is run on its own.


Finally, as mentioned in other answers, it can be useful to do nothing when an exception is caught:

try:
    n[i] = 0
except IndexError:
    pass

回答 3

最好和最准确的思考pass方式是明确告诉解释器不执行任何操作的方式。以同样的方式执行以下代码:

def foo(x,y):
    return x+y

意思是“如果我调用函数foo(x,y),将标签x和y代表的两个数字相加并返回结果”,

def bar():
    pass

表示“如果我调用函数bar(),则绝对不执行任何操作。”

其他答案非常正确,但是对于一些不涉及占位的事情也很有用。

例如,在我最近使用的一些代码中,有必要将两个变量相除,并且除数可能为零。

c = a / b

如果b为零,显然会产生ZeroDivisionError。在这种特殊情况下,在b为零的情况下,将c保留为零是理想的行为,因此我使用以下代码:

try:
    c = a / b
except ZeroDivisionError:
    pass

另一个较少使用的标准用法是为调试器放置断点的方便位置。例如,我想在for … in语句的第20次迭代中将一些代码插入调试器。所以:

for t in range(25):
    do_a_thing(t)
    if t == 20:
        pass

断点通过。

The best and most accurate way to think of pass is as a way to explicitly tell the interpreter to do nothing. In the same way the following code:

def foo(x,y):
    return x+y

means “if I call the function foo(x, y), sum the two numbers the labels x and y represent and hand back the result”,

def bar():
    pass

means “If I call the function bar(), do absolutely nothing.”

The other answers are quite correct, but it’s also useful for a few things that don’t involve place-holding.

For example, in a bit of code I worked on just recently, it was necessary to divide two variables, and it was possible for the divisor to be zero.

c = a / b

will, obviously, produce a ZeroDivisionError if b is zero. In this particular situation, leaving c as zero was the desired behavior in the case that b was zero, so I used the following code:

try:
    c = a / b
except ZeroDivisionError:
    pass

Another, less standard usage is as a handy place to put a breakpoint for your debugger. For example, I wanted a bit of code to break into the debugger on the 20th iteration of a for… in statement. So:

for t in range(25):
    do_a_thing(t)
    if t == 20:
        pass

with the breakpoint on pass.


回答 4

可以“按原样”使用的常见用例是重写类,仅是为了创建类型(否则与超类相同),例如

class Error(Exception):
    pass

因此,您可以引发并捕获Error异常。这里重要的是异常的类型,而不是内容。

A common use case where it can be used ‘as is’ is to override a class just to create a type (which is otherwise the same as the superclass), e.g.

class Error(Exception):
    pass

So you can raise and catch Error exceptions. What matters here is the type of exception, rather than the content.


回答 5

pass在Python中基本上不执行任何操作,但是与注释不同,解释器不会忽略它。因此,可以通过将其设置为占位符来在很多地方利用它:

1:可以在课堂上使用

   class TestClass: 
      pass

2:可以在循环和条件语句中使用:

   if (something == true):  # used in conditional statement
       pass

   while (some condition is true):  # user is not sure about the body of the loop
       pass

3:可用于功能:

   def testFunction(args): # programmer wants to implement the body of the function later
       pass

pass通常在程序员不愿提供实现但仍希望创建某个类/函数/条件语句(以后可以使用)时使用。由于Python解释器不允许空白或未实现的类/函数/条件语句,因此会产生错误:

IndentationError:应缩进的块

pass 可以在这种情况下使用。

pass in Python basically does nothing, but unlike a comment it is not ignored by interpreter. So you can take advantage of it in a lot of places by making it a place holder:

1: Can be used in class

   class TestClass: 
      pass

2: Can be use in loop and conditional statements:

   if (something == true):  # used in conditional statement
       pass

   while (some condition is true):  # user is not sure about the body of the loop
       pass

3: Can be used in function :

   def testFunction(args): # programmer wants to implement the body of the function later
       pass

pass is mostly used when programmer does not want to give implementation at the moment but still wants to create a certain class/function/conditional statement which can be used later on. Since the Python interpreter does not allow for blank or unimplemented class/function/conditional statement it gives an error:

IndentationError: expected an indented block

pass can be used in such scenarios.


回答 6

可以说,通过表示NOP(无操作)操作。在此示例后,您将获得清晰的图片:

C程序

#include<stdio.h>

void main()
{
    int age = 12;

    if( age < 18 )
    {
         printf("You are not adult, so you can't do that task ");
    }
    else if( age >= 18 && age < 60)
    {
        // I will add more code later inside it 
    }
    else
    {
         printf("You are too old to do anything , sorry ");
    }
}

现在,您将如何在Python中编写它:-

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

else:

    print "You are too old to do anything , sorry "

但是您的代码会出错,因为它需要在elif之后缩进一个块。这是pass关键字的作用。

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

    pass

else:

    print "You are too old to do anything , sorry "

现在,我认为这很清楚。

You can say that pass means NOP (No Operation) operation. You will get a clear picture after this example :-

C Program

#include<stdio.h>

void main()
{
    int age = 12;

    if( age < 18 )
    {
         printf("You are not adult, so you can't do that task ");
    }
    else if( age >= 18 && age < 60)
    {
        // I will add more code later inside it 
    }
    else
    {
         printf("You are too old to do anything , sorry ");
    }
}

Now how you will write that in Python :-

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

else:

    print "You are too old to do anything , sorry "

But your code will give error because it required an indented block after elif . Here is the role of pass keyword.

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

    pass

else:

    print "You are too old to do anything , sorry "

Now I think its clear to you.


回答 7

我喜欢在进行测试时使用它。我经常知道自己想测试什么,但不太了解该怎么做。测试示例看起来像sebastian_oe所建议的

class TestFunctions(unittest.TestCase):

   def test_some_feature(self):
      pass

   def test_some_other_feature(self):
      pass

I like to use it when stubbing out tests. I often times am aware of what i would like to test but don’t quite know how to do it. Testing example looks like what sebastian_oe suggested

class TestFunctions(unittest.TestCase):

   def test_some_feature(self):
      pass

   def test_some_other_feature(self):
      pass

回答 8

pass语句不执行任何操作。当在语法上需要一条语句但该程序不需要任何操作时,可以使用它。

The pass statement does nothing. It can be used when a statement is required syntactically but the program requires no action.


回答 9

老实说,我认为Python官方文档对此进行了很好的描述并提供了一些示例:

语句什么也不做。当在语法上需要一条语句但该程序不需要任何操作时,可以使用它。例如:

>>> while True: ... pass # Busy-wait for keyboard interrupt (Ctrl+C) ...

这通常用于创建最少的类:

>>> class MyEmptyClass: ... pass ...

当您在处理新代码时,可以使用另一个地方通行证作为函数或条件主体的占位符,从而使您可以继续进行更抽象的思考。该被自动忽略:

>>> def initlog(*args): ... pass # Remember to implement this! ...

Honestly, I think the official Python docs describe it quite well and provide some examples:

The pass statement does nothing. It can be used when a statement is required syntactically but the program requires no action. For example:

>>> while True: ... pass # Busy-wait for keyboard interrupt (Ctrl+C) ...

This is commonly used for creating minimal classes:

>>> class MyEmptyClass: ... pass ...

Another place pass can be used is as a place-holder for a function or conditional body when you are working on new code, allowing you to keep thinking at a more abstract level. The pass is silently ignored:

>>> def initlog(*args): ... pass # Remember to implement this! ...


回答 10

如书中所述,我只曾将其用作临时占位符,即

# code that does something to to a variable, var
if var == 2000:
    pass
else:
    var += 1

然后填写场景 var == 2000

as the book said, I only ever use it as a temporary placeholder, ie,

# code that does something to to a variable, var
if var == 2000:
    pass
else:
    var += 1

and then later fill in the scenario where var == 2000


回答 11

传递是指忽略…。就这么简单….如果给定条件为真,并且下一条语句通过,它将忽略该值或迭代并继续执行下一行…..示例

For i in range (1,100):
    If i%2==0:
                  Pass 
    Else:
                  Print(i)

输出:打印1-100中的所有奇数

这是因为偶数的模数等于零,因此它忽略该数并继续到下一个数字,因为奇数模数不等于零,则执行循环的其他部分并将其打印出来

Pass refers to ignore….as simple as it is ….if the given condition is true and the next statement is pass it ignores that value or iteration and proceed to the next line ….. Example

For i in range (1,100):
    If i%2==0:
                  Pass 
    Else:
                  Print(i)

Output: Prints all the odd numbers from 1-100

This is because modulus of even number is equal to zero ,hence it ignores the number and proceeds to next number ,since odd numbers modulus is not equal to zero the Else part of the loop is executed and its printed


回答 12

这是一个示例,其中我从具有多种数据类型的列表中提取特定数据(这就是我在R中所称的名称,如果命名错误,对不起),我只想提取整数/数字和非字符数据。

数据如下:

>>> a = ['1', 'env', '2', 'gag', '1.234', 'nef']
>>> data = []
>>> type(a)
<class 'list'>
>>> type(a[1])
<class 'str'>
>>> type(a[0])
<class 'str'>

我想删除所有字母字符,所以我让机器通过设置数据子集并“传递”字母数据来做到这一点:

a = ['1', 'env', '2', 'gag', '1.234', 'nef']
data = []
for i in range(0, len(a)):
    if a[i].isalpha():
        pass
    else:
        data.append(a[i])
print(data)
['1', '2', '1.234']

Here’s an example where I was extracting particular data from a list where I had multiple data types (that’s what I’d call it in R– sorry if it’s the wrong nomenclature) and I wanted to extract only integers/numeric and NOT character data.

The data looked like:

>>> a = ['1', 'env', '2', 'gag', '1.234', 'nef']
>>> data = []
>>> type(a)
<class 'list'>
>>> type(a[1])
<class 'str'>
>>> type(a[0])
<class 'str'>

I wanted to remove all alphabetical characters, so I had the machine do it by subsetting the data, and “passing” over the alphabetical data:

a = ['1', 'env', '2', 'gag', '1.234', 'nef']
data = []
for i in range(0, len(a)):
    if a[i].isalpha():
        pass
    else:
        data.append(a[i])
print(data)
['1', '2', '1.234']

回答 13

在语法上需要语句但您不希望执行任何命令或代码时,使用Python中的pass语句。

pass语句是一个空操作;执行时没有任何反应。在您的代码最终可以使用但尚未编写的地方(例如,在存根中),该传递也是有用的:

`示例:

#!/usr/bin/python

for letter in 'Python': 
   if letter == 'h':
      pass
      print 'This is pass block'
   print 'Current Letter :', letter

print "Good bye!"

这将产生以下结果:

Current Letter : P
Current Letter : y
Current Letter : t
This is pass block
Current Letter : h
Current Letter : o
Current Letter : n
Good bye!

如果字母的值为“ h”,则前面的代码不执行任何语句或代码。当您创建了代码块后,pass语句很有用,但不再需要。

然后,您可以删除该块内的语句,但让该块与pass语句一起保留,以免干扰代码的其他部分。

The pass statement in Python is used when a statement is required syntactically but you do not want any command or code to execute.

The pass statement is a null operation; nothing happens when it executes. The pass is also useful in places where your code will eventually go, but has not been written yet (e.g., in stubs for example):

`Example:

#!/usr/bin/python

for letter in 'Python': 
   if letter == 'h':
      pass
      print 'This is pass block'
   print 'Current Letter :', letter

print "Good bye!"

This will produce following result:

Current Letter : P
Current Letter : y
Current Letter : t
This is pass block
Current Letter : h
Current Letter : o
Current Letter : n
Good bye!

The preceding code does not execute any statement or code if the value of letter is ‘h’. The pass statement is helpful when you have created a code block but it is no longer required.

You can then remove the statements inside the block but let the block remain with a pass statement so that it doesn’t interfere with other parts of the code.


回答 14

pass用于避免python中的缩进错误如果我们采用c,c ++,java之类的语言,则它们具有大括号,例如

 if(i==0)
 {}
 else
 {//some code}

但是在python中,它使用缩进而不是花括号,因此为了避免此类错误,我们使用pass。在玩测验时记得

 if(dont_know_the_answer)
      pass

示例程序

  for letter in 'geeksforgeeks':
        pass
  print 'Last Letter :', letter

pass is used to avoid indentation error in python If we take languages like c,c++,java they have braces like

 if(i==0)
 {}
 else
 {//some code}

But in python it used indentation instead of braces so to avoid such errors we use pass. Remembered as you were playing a quiz and

 if(dont_know_the_answer)
      pass

Example program,

  for letter in 'geeksforgeeks':
        pass
  print 'Last Letter :', letter

如何使用datetime Python模块计算从当前日期起六个月的日期?

问题:如何使用datetime Python模块计算从当前日期起六个月的日期?

我正在使用datetime Python模块。我想计算从当前日期起6个月的日期。有人可以给我一点帮助吗?

我要从当前日期起6个月生成日期的原因是要产生一个审阅日期。如果用户将数据输入到系统中,则其输入日期为6个月。

I am using the datetime Python module. I am looking to calculate the date 6 months from the current date. Could someone give me a little help doing this?

The reason I want to generate a date 6 months from the current date is to produce a review date. If the user enters data into the system it will have a review date of 6 months from the date they entered the data.


回答 0

我发现此解决方案很好。(这使用python-dateutil扩展名

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

这种方法的优点是可以处理28、30、31天等问题。这在处理业务规则和业务情景(例如生成发票等)时非常有用。

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)

I found this solution to be good. (This uses the python-dateutil extension)

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

The advantage of this approach is that it takes care of issues with 28, 30, 31 days etc. This becomes very useful in handling business rules and scenarios (say invoice generation etc.)

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)

回答 1

好吧,这取决于您从当前日期算起的6个月的意思。

  1. 使用自然月份:

    (day, month, year) = (day, (month + 5) % 12 + 1, year + (month + 5)/12)
  2. 使用银行家的定义6 * 30:

    date += datetime.timedelta(6 * 30)

Well, that depends what you mean by 6 months from the current date.

  1. Using natural months:

    (day, month, year) = (day, (month + 5) % 12 + 1, year + (month + 5)/12)
    
  2. Using a banker’s definition, 6*30:

    date += datetime.timedelta(6 * 30)
    

回答 2

使用Python 3.x,您可以这样做:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

但您将需要安装python-dateutil模块:

pip install python-dateutil

With Python 3.x you can do it like this:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

but you will need to install python-dateutil module:

pip install python-dateutil

回答 3

对于月初的计算:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)

For beginning of month to month calculation:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)

回答 4

“ 6个月”是什么意思?

是2009-02-13 + 6个月== 2009-08-13吗?还是2009-02-13 + 6 * 30天?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

有关mx.DateTime的更多信息

What do you mean by “6 months”?

Is 2009-02-13 + 6 months == 2009-08-13? Or is it 2009-02-13 + 6*30 days?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

More info about mx.DateTime


回答 5

因此,这是一个示例dateutil.relativedelta,我发现该示例可用于遍历过去的一年,每次都跳过一个月到当前日期:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

与其他答案一样,您必须弄清楚“从现在起6个月后”的实际含义。如果您的意思是“未来六年的每月的当日”,则可以这样做:

datetime.datetime.now() + relativedelta(months=6)

So, here is an example of the dateutil.relativedelta which I found useful for iterating through the past year, skipping a month each time to the present date:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

As with the other answers, you have to figure out what you actually mean by “6 months from now.” If you mean “today’s day of the month in the month six years in the future” then this would do:

datetime.datetime.now() + relativedelta(months=6)

回答 6

此解决方案在12月正确运行,而此页面上的大多数答案都无效。在使用模数(%)或整数除法(//)之前,您需要首先将月份从基数1(即Jan = 1)转换为基数0(即Jan = 0),否则11月(11)加1个月为您提供12 ,当找到余数(12%12)时得到0。

(也不要建议“((月%12)+ 1”或10月+1 = 12月!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = int(d.year + ((( d.month - 1) + x ) / 12 ))
    return datetime.date( newyear, newmonth, d.day)

但是…这不能解决1月31日+一个月之类的问题。因此,我们回到OP-您增加一个月意味着什么?一种解决方案是回溯到有效的一天,因为大多数人会假设jan的最后一天加上一个月等于2月的最后一天。这也适用于负数个月。证明:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 

This solution works correctly for December, which most of the answers on this page do not. You need to first shift the months from base 1 (ie Jan = 1) to base 0 (ie Jan = 0) before using modulus ( % ) or integer division ( // ), otherwise November (11) plus 1 month gives you 12, which when finding the remainder ( 12 % 12 ) gives 0.

(And dont suggest “(month % 12) + 1” or Oct + 1 = december!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = int(d.year + ((( d.month - 1) + x ) / 12 ))
    return datetime.date( newyear, newmonth, d.day)

However … This doesnt account for problem like Jan 31 + one month. So we go back to the OP – what do you mean by adding a month? One solution is to backtrack until you get to a valid day, given that most people would presume the last day of jan, plus one month, equals the last day of Feb. This will work on negative numbers of months too. Proof:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 

回答 7

我知道这是6个月,但是如果您要添加一个月,答案就会在Google中显示为“在python中添加月份”:

import calendar

date = datetime.date.today()    //Or your date

datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

这将计算当月的天数并将其添加到当前日期,使用365/12表示一年的1/12会导致短/长月份的问题(如果您对该日期进行迭代)。

I know this was for 6 months, however the answer shows in google for “adding months in python” if you are adding one month:

import calendar

date = datetime.date.today()    //Or your date

datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

this would count the days in the current month and add them to the current date, using 365/12 would ad 1/12 of a year can causes issues for short / long months if your iterating over the date.


回答 8

没有直接的方法可以使用Python的日期时间。

python-dateutil处检查relativedelta类型。它允许您指定以月为单位的时间增量。

There’s no direct way to do it with Python’s datetime.

Check out the relativedelta type at python-dateutil. It allows you to specify a time delta in months.


回答 9

只需使用timetuple方法提取月份,添加月份并构建一个新的dateobject。如果有一个已经存在的方法,我不知道。

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

该API有点笨拙,但仅作为示例。显然也不适用于2008-01-31 + 1个月等极端情况。:)

Just use the timetuple method to extract the months, add your months and build a new dateobject. If there is a already existing method for this I do not know it.

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

The API is a bit clumsy, but works as an example. Will also obviously not work on corner-cases like 2008-01-31 + 1 month. :)


回答 10

Dateutil软件包具有此类功能的实现。但是请注意,正如其他人已经指出的那样,这将是幼稚的

Dateutil package has implementation of such functionality. But be aware, that this will be naive, as others pointed already.


回答 11

使用Python标准库(即不使用dateutil或不使用其他库)并解决“ 2月31日”问题:

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date

测试:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))

Using Python standard libraries, i.e. without dateutil or others, and solving the ‘February 31st’ problem:

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date

Testing:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))

回答 12

我有一个更好的方法来解决“ 2月31日”问题:

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

我认为它也可以使用负数(减去数月),但是我还没有对此进行太多测试。

I have a better way to solve the ‘February 31st’ problem:

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

I think that it also works with negative numbers (to subtract months), but I haven’t tested this very much.


回答 13

PyQt4的QDate类具有addmonths函数。

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)

The QDate class of PyQt4 has an addmonths function.

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)

回答 14

这个怎么样?不使用其他库(dateutil)或timedelta?在vartec的答案的基础上,我做到了,并且我相信它是有效的:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

我尝试使用timedelta,但是因为它是在计算天数,365/2或者6*356/12并不总是转换为6个月,而是182天。例如

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

我相信我们通常会假设从某天起的6个月会在该月的同一天,但会在6个月后(即2015-03-10-> 2015-09-10,不是2015-09-08

我希望你觉得这有帮助。

How about this? Not using another library (dateutil) or timedelta? building on vartec‘s answer I did this and I believe it works:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

I tried using timedelta, but because it is counting the days, 365/2 or 6*356/12 does not always translate to 6 months, but rather 182 days. e.g.

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

I believe that we usually assume that 6 month’s from a certain day will land on the same day of the month but 6 months later (i.e. 2015-03-10 –> 2015-09-10, Not 2015-09-08)

I hope you find this helpful.


回答 15

这不能回答特定的问题(datetime仅使用),但是,鉴于其他人建议使用不同的模块,此处提供了一个解决方案using pandas

import datetime as dt
import pandas as pd

date = dt.date.today() - \
       pd.offsets.DateOffset(months=6)

print(date)

2019-05-04 00:00:00

在leap年中可以正常工作

date = dt.datetime(2019,8,29) - \
       pd.offsets.DateOffset(months=6)
print(date)

2019-02-28 00:00:00

This doesn’t answer the specific question (using datetime only) but, given that others suggested the use of different modules, here there is a solution using pandas.

import datetime as dt
import pandas as pd

date = dt.date.today() - \
       pd.offsets.DateOffset(months=6)

print(date)

2019-05-04 00:00:00

Which works as expected in leap years

date = dt.datetime(2019,8,29) - \
       pd.offsets.DateOffset(months=6)
print(date)

2019-02-28 00:00:00

回答 16

修改了AddMonths()以在Zope中使用并处理无效的天数:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)

Modified the AddMonths() for use in Zope and handling invalid day numbers:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)

回答 17

import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(tuple(t)))
import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(tuple(t)))

回答 18

import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __name__ == '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))
import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __name__ == '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))

回答 19

在1new_month = 121的情况下修改了Johannes Wei的答案。这对我来说非常有效。月份可以是正数或负数。

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)

Modified Johannes Wei’s answer in the case 1new_month = 121. This works perfectly for me. The months could be positive or negative.

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)

回答 20

另一个解决方案-希望有人会喜欢它:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

此解决方案在所有情况下都无法正常工作29,30,31天,因此需要更强大的解决方案(现在不再那么好了:)):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")

Yet another solution – hope someone will like it:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

This solution doesn’t work for days 29,30,31 for all cases, so more robust solution is needed (which is not so nice anymore :) ):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")

回答 21

这个答案,看到parsedatetime。代码示例如下。更多详细信息:单元测试包含许多自然语言-> YYYY-MM-DD转换示例,以及明显的parsedatetime转换挑战/错误

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

上面的代码从MacOSX计算机生成以下代码:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 

From this answer, see parsedatetime. Code example follows. More details: unit test with many natural-language -> YYYY-MM-DD conversion examples, and apparent parsedatetime conversion challenges/bugs.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

The above code generates the following from a MacOSX machine:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 

回答 22

这是一个示例,它使用户可以决定如何返回日期大于月份中天数的日期。

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)

Here’s a example which allows the user to decide how to return a date where the day is greater than the number of days in the month.

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)

回答 23

假设您的datetime变量称为date:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)

given that your datetime variable is called date:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)

回答 24

获取x个月之后/之前的下一个日期的常规功能。

从日期时间导入日期

def after_month(给定日期,月份):
    yyyy = int((((给定日期。年* 12 +给定日期。月)+月)/ 12)
    mm = int((((给定日期。年* 12 +给定日期。月)+月)%12)

    如果mm == 0:
        yyyy-= 1
        毫米= 12
    返回给定的date.replace(年= yyyy,月= mm)


如果__name__ ==“ __main__”:
    今天= date.today()
    打印(今天)

    对于[-12,-1,0,1,2,12,20]中的mm:
        next_date = after_month(今天,毫米)
        打印(下一个日期)

General function to get next date after/before x months.

from datetime import date

def after_month(given_date, month):
    yyyy = int(((given_date.year * 12 + given_date.month) + month)/12)
    mm = int(((given_date.year * 12 + given_date.month) + month)%12)

    if mm == 0:
        yyyy -= 1
        mm = 12
    return given_date.replace(year=yyyy, month=mm)


if __name__ == "__main__":
    today = date.today()
    print(today)

    for mm in [-12, -1, 0, 1, 2, 12, 20 ]:
        next_date = after_month(today, mm)
        print(next_date)

回答 25

一个快速的建议是箭头

点安装箭头

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)

A quick suggestion is Arrow

pip install arrow

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)

回答 26

使用python datetime模块将六个月的时间增量添加到datetime.today()。

http://docs.python.org/library/datetime.html

当然,你将要解决什么约翰内斯Weiß–提出的问题你6个月意味着什么呢?

Use the python datetime module to add a timedelta of six months to datetime.today() .

http://docs.python.org/library/datetime.html

You will of course have to solve the issue raised by Johannes Weiß– what do you mean by 6 months?


回答 27

这就是我想出的。它可以移动正确的月数和年数,但会忽略天数(这是我当时所需要的)。

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)

This is what I came up with. It moves the correct number of months and years but ignores days (which was what I needed in my situation).

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)

回答 28

我使用此功能更改年份和月份,但保留日期:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

您应该写:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)

I use this function to change year and month but keep day:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

You should write:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)

回答 29

我认为这样做比手动添加天数更安全:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

newdate = addMonths(today, 6)

I think it would be safer to do something like this instead of manually adding days:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

newdate = addMonths(today, 6)

“ with”语句中有多个变量?

问题:“ with”语句中有多个变量?

使用withPython中的语句可以声明多个变量吗?

就像是:

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

…还是同时清理两个资源是问题吗?

Is it possible to declare more than one variable using a with statement in Python?

Something like:

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

… or is cleaning up two resources at the same time the problem?


回答 0

从v3.1Python 2.7 开始,Python 3中是可能的。新with语法支持多个上下文管理器:

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

不同于contextlib.nested,这保证了即使或方法引发异常,ab__exit__()调用C()__enter__()

您也可以在较新的定义中使用较早的变量(以下为h / t Ahmad):

with A() as a, B(a) as b, C(a, b) as c:
    doSomething(a, c)

It is possible in Python 3 since v3.1 and Python 2.7. The new with syntax supports multiple context managers:

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

Unlike the contextlib.nested, this guarantees that a and b will have their __exit__()‘s called even if C() or it’s __enter__() method raises an exception.

You can also use earlier variables in later definitions (h/t Ahmad below):

with A() as a, B(a) as b, C(a, b) as c:
    doSomething(a, c)

回答 1

contextlib.nested 支持这一点:

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

更新:
要引用有关contextlib.nested以下内容的文档:

从2.7版开始不推荐使用:with语句现在直接支持此功能(不存在容易出错的易错问题)。

有关更多信息,请参见RafałDowgird的答案

contextlib.nested supports this:

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

Update:
To quote the documentation, regarding contextlib.nested:

Deprecated since version 2.7: The with-statement now supports this functionality directly (without the confusing error prone quirks).

See Rafał Dowgird’s answer for more information.


回答 2

请注意,如果将变量分成几行,则必须使用反斜杠来包装换行符。

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

括号无效,因为Python会创建一个元组。

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

由于元组缺少__enter__属性,因此会出现错误(描述性不够,并且无法标识类类型):

AttributeError: __enter__

如果尝试as在括号内使用,Python会在解析时捕获错误:

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)

SyntaxError:语法无效

https://bugs.python.org/issue12782似乎与此问题有关。

Note that if you split the variables into lines, you must use backslashes to wrap the newlines.

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

Parentheses don’t work, since Python creates a tuple instead.

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

Since tuples lack a __enter__ attribute, you get an error (undescriptive and does not identify class type):

AttributeError: __enter__

If you try to use as within parentheses, Python catches the mistake at parse time:

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)

SyntaxError: invalid syntax

https://bugs.python.org/issue12782 seems to be related to this issue.


回答 3

我认为您想这样做:

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

I think you want to do this instead:

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

回答 4

因为Python 3.3,你可以使用类ExitStackcontextlib模块。

它可以管理动态数量的上下文感知对象,这意味着如果您不知道要处理多少文件,它将证明特别有用。

文档中提到的规范用例正在管理动态文件数量。

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

这是一个通用示例:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(stack._exit_callbacks)
    nums = [stack.enter_context(x) for x in xs]
    print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)

输出:

deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]

Since Python 3.3, you can use the class ExitStack from the contextlib module.

It can manage a dynamic number of context-aware objects, which means that it will prove especially useful if you don’t know how many files you are going to handle.

The canonical use-case that is mentioned in the documentation is managing a dynamic number of files.

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

Here is a generic example:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(stack._exit_callbacks)
    nums = [stack.enter_context(x) for x in xs]
    print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)

Output:

deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]

回答 5

在Python 3.1+中,您可以指定多个上下文表达式,它们将像with嵌套了多个语句一样进行处理:

with A() as a, B() as b:
    suite

相当于

with A() as a:
    with B() as b:
        suite

这也意味着您可以在第二个表达式中使用第一个表达式的别名(在使用数据库连接/游标时很有用):

with get_conn() as conn, conn.cursor() as cursor:
    cursor.execute(sql)

In Python 3.1+ you can specify multiple context expressions, and they will be processed as if multiple with statements were nested:

with A() as a, B() as b:
    suite

is equivalent to

with A() as a:
    with B() as b:
        suite

This also means that you can use the alias from the first expression in the second (useful when working with db connections/cursors):

with get_conn() as conn, conn.cursor() as cursor:
    cursor.execute(sql)