抛出错误的Python - 字符串索引必须是整数

时间:2014-06-14 15:35:40

标签: python sqlite xbmc

我使用版本2.6 for XBMC媒体应用程序处理我的python脚本。

我的python脚本出了问题,我试图从sqlite3数据库中删除数据,但我收到错误TypeError: string indices must be integers

错误是跳到这一行:

programming = channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"]

以下是完整代码:

import xbmc
import xbmcgui
import xbmcaddon
import os
import urllib2
import StringIO
import sqlite3
from sqlite3 import dbapi2 as database
from xml.etree import ElementTree
import xml.etree.ElementTree as ET
from UserDict import DictMixin
import datetime
import time

class MyClass(xbmcgui.WindowXML):

    def onAction(self, action):

        #DOWNLOAD THE XML SOURCE HERE
        url = ADDON.getSetting('allchannels.url')
        req = urllib2.Request(url)
        response = urllib2.urlopen(req)
        data = response.read()
        response.close()
        profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', ''))

        if os.path.exists(profilePath):
           profilePath = profilePath + 'source.db'
           con = database.connect(profilePath)
           cur = con.cursor()
           cur.execute('CREATE TABLE programs(channel TEXT, title TEXT, start_date TIMESTAMP, stop_date TIMESTAMP, description TEXT)')
           con.commit()
           con.close
           tv_elem = ElementTree.parse(StringIO.StringIO(data)).getroot()
           profilePath = xbmc.translatePath(os.path.join('special://userdata/addon_data/script.tvguide', ''))
           profilePath = profilePath + 'source.db'
           con = sqlite3.connect(profilePath)
           cur = con.cursor()
           channels = OrderedDict()

           # Get the loaded data
           for channel in tv_elem.findall('channel'):
                channel_name = channel.find('display-name').text
                for program in channel.findall('programme'):
                   title = program.find('title').text
                   start_time = program.get("start")
                   stop_time = program.get("stop")
                   cur.execute("INSERT INTO programs(channel, title, start_date, stop_date)" + " VALUES(?, ?, ?, ?)", [channel_name, title, start_time, stop_time])
                   con.commit()
                   print 'Channels store into database are now successfully!'

                   cur.execute('SELECT channel, title, start_date, stop_date FROM programs')
                   programList = list()
                   channelMap = dict()
                   results = cur.fetchall()
                   cur.close


                   for channel_result in results:
                      for row in channel_result:
                         programming = channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"]
                         print(programming)

我在XBMC日志中一直收到同样的错误请求。

编辑:当我尝试这个时:

programList = list()
channelMap = dict()
for c in channels:
if c.id:
   channelMap[c.id] = c
   strCh = '(\'' + '\',\''.join(channelMap.keys()) + '\')'
   cur.execute('SELECT * FROM programs WHERE channel')
   for row in cur:
      programming = program(channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"])
      programList.append(programming)  
      print(programming)

以下是xbmc日志中的错误:

- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <type 'exceptions.TypeError'>
Error Contents: tuple indices must be integers, not str
Traceback (most recent call last):
File "C:\Users\user\AppData\Roaming\XBMC\addons\script.tvguide\test.py", line 1679, in onAction
programming = program(channelMap[row['channel']], row["title"], row["start_date"], row["stop_date"])
TypeError: tuple indices must be integers, not str
-->End of Python script error report<--

2 个答案:

答案 0 :(得分:1)

您循环遍历结果中的每一行,然后遍历每一列。 列是字符串

for channel_result in results:
    for row in channel_result:

所以channel_result是一行(默认情况下是一个元组),然后用for row in channel_result循环它。这使得每个row对象成为单个列值

您似乎期望row成为字典;这是的情况。你可以直接打印行;列的列出顺序与原始SELECT相同:

for row in results:
    programming = (channelMap[row[0]],) + row[1:]

如果你真的想要每行的字典,你必须通过在连接上设置row_factory attribute来告诉sqlite3

def dict_factory(cursor, row):
    d = {}
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d

con = sqlite3.connect(profilePath)
con.row_factory = dict_factory

之后使用一个循环:

for row in results:

row将是一个字典,其中的键对应于列名。

答案 1 :(得分:0)

如果我看对了,错误非常精确。您的返回值应该是字符串列表。因此,您需要为该行中的索引使用整数。 Python只是不知道如何处理row['channel'],因为没有为'channel'定义的索引row。 最简单的可能是尝试在那里打印行的值,然后你应该能够调试它。

以下是文档:https://docs.python.org/2/library/sqlite3.html#sqlite3.Cursor