tty Python Sqlite 应用:新手 NameError、意外 EOF 和 sqlite 错误
我正在把一个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 个回答
这里有几个事情需要注意。首先,mn
这个函数并不会返回任何东西,你可能需要用类似下面的代码:
>>> def mn():
... conn = sqlite3.connect('tester.db')
... cur = conn.cursor()
... return cur
...
>>> c = mn()
这样会留下一个打开的连接,所以当你用完 c
后,你需要调用:
>>> c.connection.close()
另外,在游标上执行的操作也不会返回任何结果,你需要调用一些 fetch
方法,比如 fetchone
或 fetchall
。把这些内容结合起来,我会开始修改成如下:
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)
在你的脚本中,你应该使用 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()