2

ニュースグループをトロールして、テキストベースのグループ化アルゴリズムをテストし、ニュースグループヘッダーのバッチをフェッチして、SQLiteデータベースに貼り付けようとしています。データベースはほぼ単純で、すべてのデータのテキスト列があり、Pythonのnntpライブラリによってフェッチされたヘッダーデータは、ヘッダーごとに常に8つの値を提供します。それらの1つを除いてすべてが文字列であり、データベースにデータを挿入する前に、文字列以外の文字列のみを文字列に変換します。これにもかかわらず、Pythonは、「TypeError:文字列のフォーマット中にすべての引数が変換されない」というかなり役に立たないエラーに陥ります。これは、「エラー:頑張ってください、あなたは自分で」と言うことからほんのわずかなステップです。

文字列から文字列への文字列フォーマットがどのようにうまくいかないかを理解している人は、次のコードで何がうまくいかないかを知っていますか?

import nntplib, sqlite3

# newsgroup settings (modify so that this works for you =)
server = 'news.yournewsgroup.com'
port = 119
username = 'your name here'
password = 'your password here'

# set up the newsgroup and sqlite connections
connection = nntplib.NNTP(server, port, username, password)
newsgroup = "comp.graphics.algorithms"
connection.group(newsgroup)
database = sqlite3.connect(newsgroup + ".db")

# create a table definition if it doesn't exist yet
try:
  # SQLite doesn't actually have data types. Everything as stored as plain text.
  # And so is newsgroup data. Bonus!
  database.execute("""CREATE TABLE headers (articleNumber text, subject text,
                                            poster text, date text, id text,
                                            references text, size text,
                                            lines text)""")
except:
  # table definition already exists. Not actually an error.
  pass

# Get the group meta-data, and set up iterator values for running
# through the header list.
resp, count, first, last, name = connection.group(newsgroup)
total = int(last) - int(first)
step = 10000
steps = total / step;
articleRange = first + '-' + str(int(first)+step)

# grab a batch of headers
print "[FETCHING HEADERS]"
resp, list = connection.xover(first, str(int(first)+step))
print "done."

# process the fetched headers
print "[PROCSSING HEADERS]"
for entry in list:
  # Unpack immutable tuple, mutate (because the references list
  # should be a string), then repack.
  articleNumber, subject, poster, date, id, references, size, lines = entry
  argumentList = (articleNumber, subject, poster, date, id, (",".join(references)), size, lines)

  try:
    # try to chronicle the header information. THIS WILL GO WRONG AT SOME POINT.
    database.execute("""INSERT INTO headers (articleNumber, subject, poster,
                                             date, id, reference, size, lines)
                                    VALUES ('?', '?', '?',
                                            '?', '?','?', '?', '?')"""
                                    % argumentList)

  except TypeError as err:
    # And here is an irking point with Python in general. Something went
    # wrong, yet all it tells us is "not all arguments converted during
    # string formatting". Despite that error being generated at a point
    # where the code knows WHICH argument was the problem.
    print err
    print type(argumentList[0]), argumentList[0]
    print type(argumentList[1]), argumentList[1]
    print type(argumentList[2]), argumentList[2]
    print type(argumentList[3]), argumentList[3]
    print type(argumentList[4]), argumentList[4]
    print type(argumentList[5]), argumentList[5]
    print type(argumentList[6]), argumentList[6]
    print type(argumentList[7]), argumentList[7]
    # A quick print set shows us that all arguments are already of type
    # "str", and none of them are empty... so it would take quite a bit
    # of work to make them fail at being legal strings... Wat?
    exit(1)
print "done."

# cleanup
database.close()
connection.quit()
4

2 に答える 2

3

そのエラーは、文字列のフォーマット(%)にn個の値を指定しているが、フォーマット文字列はn個未満の値を期待していることを示しています。具体的には、この文字列:

"""INSERT INTO headers (articleNumber, subject, poster,
                        date, id, reference, size, lines)
          VALUES ('?', '?', '?',
                  '?', '?','?', '?', '?')"""

-style文字列フォーマットの値は必要ありません。そこには何もありません、いや%、何もありません。代わりに、プレースホルダーはDBAPIのパラメーター置換用です。演算子でそれを呼び出すことはありません(ここではまったく必要ありません)。代わりに、値のシーケンスを2番目のパラメーターとして呼び出しに渡します。また、プレースホルダーから引用符を削除して、単一引用符文字を含む文字列リテラルではなく、プレースホルダーであることが想定されていることを示す必要があります。要約すれば:%d%s?%execute

database.execute("""
    INSERT INTO headers (articleNumber, subject, poster,
                         date, id, reference, size, lines)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", # note: comma, not %
     argumentList)
于 2012-11-24T17:38:16.550 に答える
0

あなたはそれをそのようにしたくありません-それは安全ではなく、エラーが発生しやすいです。

次のパターンを使用する必要があります。

argumentList = [1, 2, 3, 4, 5, 6, 7, 8] # or whatever
insert_stament = """INSERT INTO headers (articleNumber, subject, poster,
                                         date, id, reference, size, lines)
                                VALUES (?, ?, ?,
                                        ?, ?, ?, ?, ?)"""

cursor.execute(insert_statement, argumentList)
于 2012-11-24T17:33:23.903 に答える