无法将路径保存到数据库(Python/Windows)
我正在制作一个程序,目的是移动文件并把它们的新路径保存到数据库里。不过,我在拼接和执行插入数据库的SQL查询时遇到了很大的问题。
这是我的程序:
#logspc.py
import os
import sqlite3 as lite
import sys
import time
def getspc(path):
dirs = os.listdir(path)
spcfiles = []
for filename in dirs:
(shortname, extension) = os.path.splitext(filename)
if extension == '.spc':
spcfiles.append(filename)
return spcfiles
src=os.path.normpath(r'C:\users\python\nonpython')
dest=os.path.normpath(r'C:\users\python\target')
files=getspc(src)
con = lite.connect('spcbase.db')
cur=con.cursor()
for mfile in files:
oldpath=os.path.normpath(os.path.join(src,mfile))
newpath=os.path.normpath(os.path.join(dest,mfile))
os.rename(oldpath,newpath)
query="INSERT INTO spectra VALUES ('" + newpath + "',SELECT date('now'))"
print query
cur.execute(query)
con.close()
在“cur.execute(query)”这一行程序崩溃了,出现了以下错误:
Traceback (most recent call last):
File "C:/Users/Python/logspc2.py", line 27, in <module>
cur.execute(query)
OperationalError: near "SELECT": syntax error
打印出来的query变量的值是
INSERT INTO spectra VALUES ('C:\users\python\target\Bertil.spc',SELECT date('now'))
接下来我该怎么做呢?
2 个回答
我也遇到了同样的问题,找到了解决办法:
http://www.experts-exchange.com/questions/28401790/Inserting-dir-filename-to-mysql-from-Python.html
在我的程序中,我在一个微软的驱动器里进行递归搜索,fpath是在for循环中用os.path定义的。
print fpath returns -> C:\myfolder\myfile.zip
我发现它会按照打印的内容进行插入。
fpath2 = fpath.replace('\\','\\\\')
SQL = 'INSERT INTO all_zip_files(fpath_zip,status) VALUES("%s", "0");' % (fpath2)
我还发现需要以一种特殊的方式定义根目录:
PATH = r"c:\" #fails
PATH = r"c:" #works however execute(SQL) fails becaue path becomes c:myfolder\myfile.zip after using fpath.replace('\\',\\\\')
PATH = os.path.normpath("c:/") #WORKS with fpath.replace('\\','\\\\') to create desired windows path for my db
这个方法对我有效,不过这里还有一个“更好”的解决方案:
在SQLite中,获取当前日期的语法是CURRENT_DATE(CURRENT_TIME和CURRENT_TIMESTAMP也可以用):
INSERT INTO spectra VALUES ('C:\users\python\target\Bertil.spc', CURRENT_DATE)
另外,养成使用参数化查询的习惯,而不是把SQL语句写成字符串,这样做是个好习惯:
cur.execute(
'INSERT INTO spectra (PathCol, DateCol) VALUES (?, CURRENT_DATE)',
[newpath]
)
这样可以让你的程序更“安全”,因为没有人能通过把SQL代码夹带在你用来构建字符串的值中来偷偷修改你的语句。虽然在你的程序中这不是个大问题*(因为newpath
的值不是用户提供的),但如果文件名中包含一些可能让SQLite的字符串解析器困惑的字符,这样做也会有所帮助。
最后,另一个好习惯是在INSERT
语句中包含你要插入值的列名。这样可以让你的代码更稳健——如果没有列名的话,如果表的结构被重新定义,列的数量或顺序发生变化,你的代码就会出错。通过明确列出列名,你的代码可以在很多常见的表结构重新定义情况下继续正常工作。
*
其实这是个有趣的问题——在任何文件系统中,是否存在通过路径和文件名进行SQL注入的方法?我觉得这可能是可行的!