tty Python Sqlite 应用:新手 NameError、意外 EOF 和 sqlite 错误

-1 投票
2 回答
931 浏览
提问于 2025-04-16 10:55

我正在把一个tcl脚本移植到python,因为我在我的诺基亚N810上搞不定tclSqlite。这个脚本会提示输入,然后把这些输入传给一个有三个表的sqlite数据库:Notes(笔记)、Tags(标签)和一个多对多的NotesXTags表。还有一些触发器,防止我重复存储标签。作为一个新手/爱好者,我逐行查看tcl脚本,把每一行替换成python的代码。虽然这样不太符合python的风格,但我只是个爱好者,没打算在完成这个脚本后继续使用这个语言。我查看了每个StackOverflow推荐的问答,已经忙了好几个小时,但还是遇到了至少三个我不知道的错误。以下是一个名为'pythonmakenote.py'的模块中的一部分脚本:

一些注释和其他内容……

import sys, tty
import sqlite3

def mn():
    conn = sqlite3.connect('/home/j...notes.sqlite')
    db = conn.cursor()
tagsofar =db.execute('select tag_text from tag')
print tagsofar

print "Enter note text, remember to let console wrap long lines"
notetxt = input("note: ") 

print "Enter 1 or more tags separated by spaces"
taglist = input("tags: ")
taglist = taglist.split(" ")

db.execute('INSERT INTO note (note_txt) VALUES (?)', notetxt)
db.commit
fknote = db.execute('select last_insert_rowid()')

#records new tags since db trigger stops dups, updates many-many tbl

for tagtxt in taglist: 
    db.execute('INSERT INTO tag VALUES (?)',tagtxt)
    db.commit
    fktag = db.execute('select rowid from tag where tag_text = (?)',tagtxt)
    db.execute('INSERT INTO fkeys VALUES (?,?)',fknote,fktag)
    db.commit

所以我执行了'import pythonmakenote',到目前为止一切正常。我输入'mn'却出现了错误:

>>> mn
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'mn' is not defined

然后我尝试了这个:

>>> from pythonmakenote import mn
>>> mn
<function mn at 0xb76b2a74>

但'mn'还是不行。所以我干脆把Def去掉,复制文件并命名为'mn.py',结果勉强能用……

>>> import mn
<sqlite3.Cursor object at 0xb75fb740>
Enter note text, remember to let console wrap long lines
note: 'this is a note'<--------------------------Quotes are a MUST (but not in tcl version)
Enter 1 or more tags separated by spaces
tags: 'dev'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mn.py", line 19, in <module>
    db.execute('INSERT INTO note (note_txt) VALUES (?)', notetxt)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 14 supplied.<-----------------------------Huh?

在StackOverflow上,关于代码块标签和其他markdown的说明在哪里呢?

为什么我不能在一个模块里定义mn并使用它?这个Python: NameError: global name 'foobar' is not defined和我的问题有关吗?

我还有几个其他的Def需要做,比如通过标签获取笔记、获取标签列表等等,我想这些都可以放在一个模块里。

我不想在输入(笔记或用空格分隔的标签列表)周围加引号,这可以做到吗?我在里面有import tty的代码,但我没用上(不知道怎么用,但我开始怀疑我得学一下)。

当我在提示时输入三个标签而不加引号,就会出现'unexpected EOF'错误。这是为什么呢?

我知道字符串是不可变的,所以把一个之前是字符串的变量赋值为列表/分割的结果可能会有问题吗?

sqlite的'14'绑定是从哪里来的?我在用空格字符分割,但它被忽略了(可能是我做错了)?

用Bash来做我的小项目会不会更简单?

感谢任何愿意花时间看到这里的人。我有个坏习惯,就是在StackOverflow上需要帮助时问一些不相关的问题,而且在这里太菜了,不知道该查什么。我在tcl版本上挣扎了一下,但现在它运行得很好。我原以为Python会简单一些,还是觉得它可能会。

编辑:哇,很多换行被去掉了。抱歉,我不知道怎么修复。我去看看"raw_input"是否更好用。

2 个回答

1

这里有几个事情需要注意。首先,mn 这个函数并不会返回任何东西,你可能需要用类似下面的代码:

>>> def mn():
...     conn = sqlite3.connect('tester.db')
...     cur = conn.cursor()
...     return cur
... 
>>> c = mn()

这样会留下一个打开的连接,所以当你用完 c 后,你需要调用:

>>> c.connection.close()

另外,在游标上执行的操作也不会返回任何结果,你需要调用一些 fetch 方法,比如 fetchonefetchall。把这些内容结合起来,我会开始修改成如下:

import sys, tty
import sqlite3

def mn():
    conn = sqlite3.connect('/home/j...notes.sqlite')
    cur = conn.cursor()
    return cur

db = mn()

tags_so_far = db.execute('select tag_text from tag').fetchall()

print tags_so_far

print "Enter note text, remember to let console wrap long lines \n"
notetxt = raw_input("note: ")

print "Enter 1 or more tags separated by spaces \n"
taglist = raw_input("tags: ").split()

db.execute('INSERT INTO note (note_txt) VALUES (?)', notetxt)
db.commit()

fknote = db.execute('select last_insert_rowid()').fetchone()[0]

#records new tags since db trigger stops dups, updates many-many tbl

for tagtxt in taglist:
    db.execute('INSERT INTO tag VALUES (?)', (tagtxt,))
    db.commit()
    fktag = db.execute('select rowid from tag where tag_text = (?)',tagtxt)
    db.execute('INSERT INTO fkeys VALUES (?,?)',fknote,fktag)
2

在你的脚本中,你应该使用 raw_input 而不是 input。因为 input 会对你输入的内容进行计算,所以你必须输入引号。

你可以使用输入窗口上方的 {} 按钮来格式化代码。实际上,代码的格式化是通过在前面加上4个空格来实现的。

db.commit 需要写成 db.commit()

如果你这样做:

>>> import pythonmakenote

要运行 mn,你可以这样做:

>>> pythonmakenote.mn()

你也可以这样做:

>>> from pythonmakenote import mn
>>> mn()

对于像这样的行:

db.execute('INSERT INTO note (note_txt) VALUES (?)', notetxt)

你需要:

db.execute('INSERT INTO note (note_txt) VALUES (?)', (notetxt,))

execute 期待一个序列,所以如果你传入一个字符串,它会把这个字符串当作单个字符的序列,这就是你看到的 14 bindings 错误(因为它是一个14个字符的字符串)。(xxx,) 是表示一个元素的元组的语法。把它改成列表 [xxx] 也可以。

这是我能想到的一个可能有效的方案。我没有你的数据库:

import sys
import sqlite3

def mn():
    conn = sqlite3.connect('data.db')
    db = conn.cursor()
    db.execute('select tag_text from tag')
    tagssofar = db.fetchall()
    print tagssofar

    print "Enter note text, remember to let console wrap long lines"
    notetxt = raw_input("note: ") 

    print "Enter 1 or more tags separated by spaces"
    taglist = raw_input("tags: ")
    taglist = taglist.split()

    db.execute('INSERT INTO note (note_txt) VALUES (?)', [notetxt])
    conn.commit()
    db.execute('select last_insert_rowid()')
    fknote = db.fetchone()[0]
    print fknote

    #records new tags since db trigger stops dups, updates many-many tbl

    for tagtxt in taglist: 
        db.execute('INSERT INTO tag VALUES (?)',[tagtxt])
        conn.commit()
        db.execute('select rowid from tag where tag_text = (?)',[tagtxt])
        fktag = db.fetchone()[0]
        print fktag
        db.execute('INSERT INTO fkeys VALUES (?,?)',[fknote,fktag])
        conn.commit()

撰写回答