"import datetime" 和 "from datetime import datetime" 的区别。

69

我有一个脚本,需要在不同的行执行以下操作:

today_date = datetime.date.today()
date_time = datetime.strp(date_time_string, '%Y-%m-%d %H:%M')

在我的import语句中,我有以下内容:

from datetime import datetime
import datetime

我遇到了以下错误:

AttributeError: 'module' object has no attribute 'strp'

如果我将 import 语句的顺序更改为:

import datetime
from datetime import datetime

我遇到了以下错误:

AttributeError: 'method_descriptor' object has no attribute 'today'

如果我再次更改import语句为:

import datetime

我遇到了以下错误:

AttributeError: 'module' object has no attribute 'strp'

这里发生了什么事,我该如何使它们都能工作?


datetime.datetime 上也没有 strp 方法,你可能想用的是 datetime.datetime.strptime() - Martijn Pieters
6个回答

97

你的问题在于你的一些代码期望 datetime 是指向 datetime 模块的引用,而另一些代码期望 datetime 是指向 datetime 的引用。显然,它不能同时是两者。

当你执行以下操作时:

from datetime import datetime
import datetime

你首先将datetime设置为一个类的引用,然后立即将其设置为模块的引用。如果你按相反的顺序进行操作,则它最终将成为对该类的引用。最后的赋值“获胜”。

你需要重命名其中一个引用。例如:

import datetime as dt
from datetime import datetime

然后你可以将引用模块的形式为datetime.xxxx的引用更改为dt.xxxx

否则,只需import datetime并更改所有引用以使用模块名称。换句话说,如果某个东西仅表示为datetime(...),您需要将该引用更改为datetime.datetime

不幸的是,Python库中有相当多这种东西。如果他们遵循PEP 8中的命名指南,则datetime类将被命名为Datetime,并且使用datetime表示模块和Datetime表示类将没有问题。


3
重命名模块似乎不是一个好的选择。要么使用 import datetime 或者 from datetime import datetime,不能同时使用两种方式。 - jfs
3
我认为最好的方法是只需执行import datetime,然后在使用该类时执行datetime.datetime。这样代码就清晰明了,且不易出错。虽然在整个代码中都要使用datetime.datetime有些烦人,但是考虑到清晰度,这个库的名称命名不太好,所以别无选择。 - Dnaiel
2
根据 @kindall 对 PEP 8 的建议,我提议使用以下代码:from datetime import datetime as DateTime, timedelta as TimeDelta, date as Date - Phil Huhn
2
@jfs,为什么改名是个不好的选择,考虑到其他模块的普遍改名: import pandas as pdimport numpy as np等。 - alancalvitti
1
@jfs,出了什么问题吗?我在争论同样的事情 - 也许我表达得太简洁了,难以理解。这个比喻是:def f()... 就像 import datetime as dt。然后在其他地方只引用 fdt,而不是函数体和 datetime(模块)。在两种情况下,通常有多个引用,并且两种情况都添加了上下文。 - alancalvitti
显示剩余5条评论

36

您不能同时使用这两个语句;datetime 模块 包含一个 datetime 类型。在您自己的模块中,本地名称 datetime 只能引用其中之一。

只使用 import datetime,然后确保始终使用 datetime.datetime 来引用包含的类型:

import datetime

today_date = datetime.date.today()
date_time = datetime.datetime.strptime(date_time_string, '%Y-%m-%d %H:%M')

现在 datetime 是一个模块,你可以通过该模块引用其中包含的类型。

或者,你也可以从该模块中导入你需要的 所有 类型:

from datetime import date, datetime

today_date = date.today()
date_time = datetime.strptime(date_time_string, '%Y-%m-%d %H:%M')

这里的datetime是从模块中获取的一种类型。而date则是同一模块中的另一种类型。


2
非常感谢Martijn。他们为什么要用与模块相同的名称命名类型,这让人感到困惑。我是Python和开发方面的新手,也许这是某种最佳实践。无论如何,非常感谢您的帮助。 - codingknob
1
@codingknob 这不是他们搞错了吗。官方的Python风格指南(PEP8)明确规定要以不同的名称命名事物,但我猜这段代码是在风格指南发布之前编写的。 - Fabiano
1
@Fabiano,事情是这样的:datetime是由Tim Peters开发的,他认为它是核心内置部件的一部分在2000年初(当时他和我都在Zope Corp工作)。PEP 8已经发布并确立,那时已经有将近18个月了。我知道Tim的想法,因为我记得当时的一些讨论。 - Martijn Pieters
1
@Fabiano:另一方面,Decimal早在之前就开始了,作为一个名为FixedPoint的外部项目,也是由Tim创建的(https://mail.python.org/pipermail/python-dev/2003-February/thread.html#32950)。区别在于Decimal一开始就是一个外部项目。 - Martijn Pieters
@MartijnPieters 非常有趣,感谢您提供的历史和背景,我理解他的想法,如果这确实是一个内置而不是标准库模块,避免名称冲突,那么这个名字肯定会更好。无论如何,在大局上看来,这只是一个非常小的怪癖,我认为 Python 仍然是最美丽、最精心设计的语言之一。干杯! - Fabiano
显示剩余2条评论

2

from datetime import datetime和normal import datetime的区别在于,你一次处理一个模块和一个类。

strptime函数仅存在于datetime类中,因此你必须通过模块导入类,否则在调用该函数时必须两次指定datetime。

问题在于,类名和模块名都被赋予了相同的名称,因此会产生一些混淆。


2
datetime 是一个包含一个叫做 datetime 的类型的模块。你想使用这两个东西,但是试图使用同样的名字来指代它们。这个类型和模块是两个不同的东西,你不能在程序中用名称 datetime 来同时引用它们两个。
如果你需要使用除了 datetime 类型以外的任何模块内容(显然你需要),那么你需要用 import datetime 导入该模块。然后你可以使用 datetime.date 引用“date”类型,使用 datetime.datetime 引用“datetime”类型。
你也可以这样做:
from datetime import datetime, date
today_date = date.today()
date_time = datetime.strp(date_time_string, '%Y-%m-%d %H:%M')

在这里,您只需要导入所需的名称(datetime和date类型),并直接导入它们,因此您不需要完全引用该模块。
最终,您必须决定需要使用模块中的哪些名称以及如何最好地使用它们。如果您只使用模块中的一两个内容(例如仅使用日期和时间类型),直接导入这些名称可能是可以接受的。如果您使用了许多内容,则最好导入整个模块,并使用点语法访问其中的内容,以避免在全局命名空间中混杂着特定于日期的名称。
还要注意,如果您导入模块名称本身,可以缩短名称以便于输入:
import datetime as dt
today_date = dt.date.today()
date_time = dt.datetime.strp(date_time_string, '%Y-%m-%d %H:%M')

但是请记住,如果您不使用实际的模块,则使用import datetime as dt并不能像from datetime import datetime那样缩短您的输入,因为这样您仍然需要在每个地方键入dt.datetime,而且没有人会读取您的代码并想“什么是'dt'?” - NeilG

0

试试这个:

import datetime
from datetime import datetime as dt

today_date = datetime.date.today()
date_time = dt.strptime(date_time_string, '%Y-%m-%d %H:%M')

strp()不存在。我认为你指的是strptime。


这有什么不同于只执行 dt = datetime.datetime 吗? - Eric
@Eric:不,它有相同的效果。 - BrenBarn

0
from datetime import datetime,timedelta
today=datetime.today()
print("Todays Date:",today)
yesterday=today-datetime,timedelta(days=1)
print("Yesterday date:",yesterday)
tommorrow=today+datetime.timedelta(days=1)
print("Tommorrow Date:",tommorrow)

不鼓励只提供代码的答案。请点击[编辑]并添加一些概括您的代码如何回答问题的话,或者解释您的答案与之前的答案/回答有何不同。[来自审核] - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接