属性错误:'datetime.datetime'对象没有'timestamp'属性。

29

请帮忙 - 我一直收到以下Traceback错误:

当前正在运行Python 2.0

我试图使用Python的Plotly库显示展示比特币价格的信息图表。我已经尝试在代码顶部导入datetime,但似乎没有解决问题。

Traceback (most recent call last):
  File "project_one.py", line 165, in <module>
    crypto_price_df = get_crypto_data(coinpair)
  File "project_one.py", line 155, in get_crypto_data
    json_url = base_polo_url.format(poloniex_pair, start_date.timestamp(), end_date.timestamp(), pediod)
AttributeError: 'datetime.datetime' object has no attribute 'timestamp'

我的代码从这里开始

import numpy as np
import pandas as pd
from pandas import Series, DataFrame, Panel
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')
import seaborn as sns
import sklearn as sk
import scipy as sp
import os
import pickle
import quandl
import datetime
import plotly.plotly as py
import plotly.graph_objs as go
import plotly.figure_factory as ff
from plotly import tools
from plotly.offline import iplot, init_notebook_mode
from IPython.display import display, HTML
init_notebook_mode(connected=True)


def get_quandl_data(quandl_id):

    cache_path = '{}.pkl'.format(quandl_id).replace('/','-')
    try:
        f = open(cache_path, 'rb')
        df = pickle.load(f)   
        print('Loaded {} from cache'.format(quandl_id))
    except (OSError, IOError) as e:
        print('Downloading {} from Quandl'.format(quandl_id))
        df = quandl.get(quandl_id, returns="pandas")
        df.to_pickle(cache_path)
        print('Cached {} at {}'.format(quandl_id, cache_path))
    return df


btc_usd_price_kraken = get_quandl_data('BCHARTS/KRAKENUSD')



exchanges = ['COINBASE','BITSTAMP','ITBIT']

exchange_data = {}

exchange_data['KRAKEN'] = btc_usd_price_kraken

for exchange in exchanges:
    exchange_code = 'BCHARTS/{}USD'.format(exchange)
    btc_exchange_df = get_quandl_data(exchange_code)
    exchange_data[exchange] = btc_exchange_df

def merge_dfs_on_column(dataframes, labels, col):

    series_dict = {}
    for index in range(len(dataframes)):
        series_dict[labels[index]] = dataframes[index][col]

    return pd.DataFrame(series_dict) 


btc_usd_datasets = merge_dfs_on_column(list(exchange_data.values()), 
list(exchange_data.keys()), 'Weighted Price')



def df_scatter(df, title, seperate_y_axis=False, y_axis_label='', 
scale='linear', initial_hide=False):

    label_arr = list(df)
    series_arr = list(map(lambda col: df[col], label_arr))

    layout = go.Layout(
        title=title,
        legend=dict(orientation="h"),
        xaxis=dict(type='date'),
        yaxis=dict(
            title=y_axis_label,
            showticklabels= not seperate_y_axis,
            type=scale
        )
    )

    y_axis_config = dict(
        overlaying='y',
        showticklabels=False,
        type=scale )

    visibility = 'visible'
    if initial_hide:
        visibility = 'legendonly'


    trace_arr = []
    for index, series in enumerate(series_arr):
        trace = go.Scatter(
            x=series.index, 
            y=series, 
            name=label_arr[index],
            visible=visibility
        )


        if seperate_y_axis:
            trace['yaxis'] = 'y{}'.format(index + 1)
            layout['yaxis{}'.format(index + 1)] = y_axis_config    
        trace_arr.append(trace)

    fig = go.Figure(data=trace_arr, layout=layout)
    py.plot(fig)



df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')


btc_usd_datasets.replace(0, np.nan, inplace=True)


df_scatter(btc_usd_datasets, 'Bitcoin Price (USD) By Exchange')


btc_usd_datasets['avg_btc_price_usd'] = btc_usd_datasets.mean(axis=1)



btc_trace = go.Scatter(x=btc_usd_datasets.index, 
y=btc_usd_datasets['avg_btc_price_usd'])
py.plot([btc_trace])



def get_json_data(json_url, cache_path):

    try:        
        f = open(cache_path, 'rb')
        df = pickle.load(f)   
        print('Loaded {} from cache'.format(json_url))
    except (OSError, IOError) as e:
        print('Downloading {}'.format(json_url))
        df = pd.read_json(json_url)
        df.to_pickle(cache_path)
        print('Cached {} at {}'.format(json_url, cache_path))
    return df

# Helper Function that Generates Poloniex API HTTP requests
base_polo_url = 'https://poloniex.com/public? 
command=returnChartData&currencyPair={}&start={}&end={}&period={}'
start_date = datetime.datetime.strptime('2015-01-01', '%Y-%m-%d') # get 
data from the start of 2015
end_date = datetime.datetime.now() # up until today
pediod = 86400 # pull daily data (86,400 seconds per day)

def get_crypto_data(poloniex_pair):

    json_url = base_polo_url.format(poloniex_pair, start_date.timestamp(), end_date.timestamp(), pediod)
    data_df = get_json_data(json_url, poloniex_pair)
    data_df = data_df.set_index('date') 
    return data_df


altcoins = ['ETH','LTC','XRP','ETC','STR','DASH','SC','XMR','XEM']
altcoin_data = {}
for altcoin in altcoins:
    coinpair = 'BTC_{}'.format(altcoin)
    crypto_price_df = get_crypto_data(coinpair)
    altcoin_data[altcoin] = crypto_price_df

你确定你正在运行Python 2.0吗?可能是2.7。 - jkr
2
timestamp 方法是在 Python 3.3 中添加的。所以如果你使用的是 Python 2.0,甚至是 2.7 版本,你就没有这个方法。你需要从 PyPI 获取一个回溯版本,从 3.3 或更高版本的源代码中复制该函数(可能需要进行一些修改使其正常工作),使用第三方库,或者升级到现代的 Python 版本。 - abarnert
7个回答

22

timestamp方法是Python 3.3中添加的。因此,如果您正在使用Python 2.0或甚至2.7,您将没有该方法。

在PyPI上有当前datetime的旧版Python版本的后端,但其中没有一个似乎是官方的或最新的;您可能希望自行搜索。

还有许多第三方替代库,它们添加了(2.x)datetime中没有的功能,包括将时间转换为Unix时间戳的能力。


您可以从3.3或更高版本的源代码中复制该函数

def timestamp(self):
    "Return POSIX timestamp as float"
    if self._tzinfo is None:
        s = self._mktime()
        return s + self.microsecond / 1e6
    else:
        return (self - _EPOCH).total_seconds()

...但你需要稍微修改一下才能让它们正常工作,因为:

  • _EPOCH 在模块末尾被删除。
  • 3.x 的 _EPOCH 是一个使用适当的 UTC 时区构建的时区感知对象,在2.x中没有除非您使用像 pytz 这样的第三方库。
  • _mktime 方法和 _tzinfo 属性在 2.x 的 datetime 中不存在,因此您需要模拟它们的功能。

如果您不需要同样适用于纯日期、GMT 和时区感知日期时间的函数,那么这并不难,但仍然不是很简单。如果您确实需要完整的功能,则会更加痛苦。


或者更容易的方法是移植文档中给出的等效代码

对于时区感知的 datetime 实例:

(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()
当然,你仍然没有那个timezone.utc,但是为了这个目的,你不需要一个完整的时区对象;你可以在2.x tzinfo 文件中使用示例UTC类的实例。对于naive:

timestamp = dt.replace(tzinfo=timezone.utc).timestamp()

…或:

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)

由于您没有意识到日期时间,那么最后一个就是您所需要的。


如果您的Python版本太旧,则可能没有timedelta__div__方法。在这种情况下(如果您没有找到回退版本),您还必须手动进行除法运算,通过对每个时间差调用total_seconds方法,确保其中至少一个为浮点数,并将数字进行除法运算:

timestamp = ((dt - datetime(1970, 1, 1)).total_seconds() / 
    float(timedelta(seconds=1).total_seconds()))

但在这种特殊情况下,很明显除数只会是1.0,而除以1.0与什么都不做是一样的,因此:

timestamp = (dt - datetime(1970, 1, 1)).total_seconds()

当我在Python 2.7中执行最后一个例子(dt - datetime(1970, 1, 1)) / timedelta(seconds=1)时,我会得到错误TypeError: unsupported operand type(s) for /: 'datetime.timedelta' and 'datetime.timedelta',而且我不知道我应该从之前的例子中获取变量/模块timezone - Mariano Ruiz
1
@MarianoRuiz 好吧,你可以选择其他选项而不是选择唯一一个在你的 Python 版本上无法工作的选项...但是如果你想知道如何在旧版本的 Python 中分割 timedeltas,我已经在新编辑中添加了另一节。 - abarnert
感谢@abarnert,最后的示例在Python 2.7中运行良好,并且您的解释非常清晰。 - Mariano Ruiz

21

正如其他回答所述,datetime.timestamp() 是在 Python 3.3 中添加的。

要在 Python < 3.3 上获得类似的行为,您需要使用 time.mktime()

import time

def to_seconds(date):
    return time.mktime(date.timetuple())

然后,你只需调用to_seconds(start_date)而不是调用start_date.timestamp()


这仅适用于naive datetimes。对于这种情况,您首先不需要time模块; 只需(date - epoch) / timedelta(seconds=1)即可。(嗯,如果它们恰好在您的本地时区中,则可以使用aware datetimes,但这不是可靠的事情。) - abarnert
1
简而言之,当您不想处理时区时,这是最佳实现。 - Selam Getachew
这个答案提供了我情况下唯一的解决方案。所有的 ... / timedelta(seconds=1) 都给了我 TypeError: unsupported operand type(s) for /: 'datetime.datetime' and 'datetime.timedelta' - Cadoiz

4

Python 3.3中添加了.timestamp()方法[来源], 因此您不能在Python 2中使用.timestamp()


3
理解易于版本无关使用的方法如下:
import datetime
import sys
if sys.version_info[0] < 3 or sys.version_info[1] < 4:
    # python version < 3.3
    import time
    def timestamp(date):
        return time.mktime(date.timetuple())
else:
    def timestamp(date):
        return date.timestamp()

# Example usecase:
date = datetime.datetime.strptime('2015-01-01', '%Y-%m-%d')
print(timestamp(date))

1
这个看起来不错;) 解决了问题 - Orsiris de Jong

0
在Python 2.x中,你所需要的就是使用time模块中的time()方法,像这样:
>>> from time import time
>>> time()
1535495731.95094

它将会给你与 Python 3.x 中 datetime 对象的 timestamp() 方法相同的结果:

>>> from datetime import datetime
>>> datetime.now().timestamp()
1535495993.949849

但这仅在您需要当前时间戳而不是任何时间戳时才有效。

官方文档:https://docs.python.org/2/library/time.html#time.time


0
这里有一个非常简单的解决方案: 在继续之前,请确保您已安装了 Python 版本 3.3 或更高版本。 您可以像这样替换运行命令。 在运行 Python 脚本之前,您以前使用的命令是:
python <your_script_name.py>

将此命令替换为以下内容:

python3 <your_script_name.py>

我希望这可以解决您的问题。


只有当使用Python 3时,此答案才是正确的,但我怀疑他们会安装新的Python版本仅仅为了使用时间戳。另外,在所有其他答案和评论中都提到了只能在Python 3中运行它,你的帖子没有带来任何新信息。 - Ruli
我发布了这个答案,只是因为如果有人使用最新版本的Python并在旧版本上运行脚本,就像我一样。我在电脑上运行的是Python >3版本,但仍然尝试使用旧版本的Python运行命令。如果其他人也在做同样的事情,他可以从我的帖子中获得帮助,而不必更改现有的脚本。 - naveen kumar

0
如果你想要计算到微秒/纳秒级别,那么你需要按照以下步骤进行操作。
import time
from datetime import datetime

timestamp_str = '2021.01.21 11:11:52:238'
dt_obj = datetime.strptime(timestamp_str, '%Y.%m.%d %H:%M:%S:%f')
timestamp = time.mktime(dt_obj.timetuple()) + dt_obj.microsecond / 1e6
timestamp_ns = int(timestamp * 1000000000)
print(timestamp_ns)

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