"与"声明适用于Windows,但不适用于Ubuntu

时间:2014-10-19 02:38:42

标签: python windows postgresql ubuntu with-statement

我有一个脚本(见下文),它在Windows中完美运行,我正在尝试迁移到Ubuntu环境。我已经设置了完全相同的PostgreSQL数据库,具有完全相同的表和用户名等。但是,当我尝试在Ubunu中运行脚本时,它在解析“with”语句时失败。

以下是“with”声明:

with con: 
    cur = con.cursor()
    cur.executemany(final_str, symbols)

我收到以下错误:

INSERT INTO symbol (ticker, instrument, name, sector, currency, created_date, last_updated_date) VALUES (%s, %s, %s, %s, %s, %s, %s) 502
Traceback (most recent call last):
  File "loadSPX.py", line 60, in <module>
    insert_snp500_symbols(symbols)
  File "loadSPX.py", line 54, in insert_snp500_symbols
    with con: 
AttributeError: __exit__

但是,如果我删除“with”并将其更改为以下内容,则可以完美地运行:

cur = con.cursor()   
cur.executemany(final_str, symbols)  
con.commit()

任何想法导致了什么?以下是完整的脚本:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import datetime
import lxml.html
import psycopg2 as mdb
import psycopg2.extras

from math import ceil


def obtain_parse_wiki_snp500():
  """Download and parse the Wikipedia list of S&P500 
  constituents using requests and libxml.

  Returns a list of tuples for to add to database."""

  # Stores the current time, for the created_at record
  now = datetime.datetime.utcnow()

  # Use libxml to download the list of S&P500 companies and obtain the symbol table
  page = lxml.html.parse('http://en.wikipedia.org/wiki/List_of_S%26P_500_companies')
  symbolslist = page.xpath('//table[1]/tr')[1:503]

  # Obtain the symbol information for each row in the S&P500 constituent table
  symbols = []
  for symbol in symbolslist:
    tds = symbol.getchildren()
    sd = {'ticker': tds[0].getchildren()[0].text,
        'name': tds[1].getchildren()[0].text,
        'sector': tds[3].text}
    # Create a tuple (for the DB format) and append to the grand list
    symbols.append( (sd['ticker'], 'stock', sd['name'], 
      sd['sector'], 'USD', now, now) )
  return symbols

def insert_snp500_symbols(symbols):
  """Insert the S&P500 symbols into the database."""

  # Connect to the PostgreSQL instance
  db_host = 'localhost'
  db_user = 'sec_user'
  db_pass = 'XXXXXXX'
  db_name = 'securities_master'
  con = mdb.connect(host=db_host, dbname=db_name, user=db_user, password=db_pass)

  # Create the insert strings
  column_str = "ticker, instrument, name, sector, currency, created_date, last_updated_date"
  insert_str = ("%s, " * 7)[:-2]
  final_str = "INSERT INTO symbol (%s) VALUES (%s)" % (column_str, insert_str)
  print final_str, len(symbols)

  # Using the MySQL connection, carry out an INSERT INTO for every symbol
  with con: 
    cur = con.cursor()
    cur.executemany(final_str, symbols)

if __name__ == "__main__":
  symbols = obtain_parse_wiki_snp500()
  insert_snp500_symbols(symbols)

1 个答案:

答案 0 :(得分:6)

你在Ubuntu上的psycopg2图书馆太旧了;您需要升级到2.5或更高版本。在旧版本中,连接尚不支持用作上下文管理器。

请参阅Psycopg 2.5 release announcement

  

连接和游标作为上下文管理器

     

最近的DBAPI扩展已将连接和游标的使用标准化为上下文管理器:现在可以使用如下的习惯用法:

with psycopg2.connect(DSN) as conn:
    with conn.cursor() as curs:
       curs.execute(SQL)
     

具有直观行为:当光标块退出时光标关闭;当连接块正常退出时,当前事务被提交,如果它以异常退出而不是事务被回滚,则在任何一种情况下连接都可以再次使用

如果您安装了python-psycopg2 system package,则最有可能使用2.4.5;只有Utopic Unicorn(14.10)有更新的版本(2.5.3)。要从soure安装较新版本,您需要安装Python开发标头(python-dev)以及PostgreSQL客户端库标头(libpq-dev)。