通过Python中的os.system在命令行上执行MySQL查询
问题描述:
我试图将while循环中的'day'传递到一个sql语句中,然后传递到MySQL命令行中执行-e通过Python中的os.system在命令行上执行MySQL查询
我不能使用DB模块或其他python库来访问MySQL,它需要通过命令行来完成。它也看起来像我可能需要将一天之前转换为一个字符串,然后连接到SQL?
#!/usr/bin/python
import datetime
a = datetime.date(2009, 1, 1)
b = datetime.date(2009, 7, 1)
one_day = datetime.timedelta(1)
day = a
while day <= b:
print day
sql="SELECT Date,SUM(CostUsd) FROM Stats d WHERE d.Date = " + day + " GROUP BY Date"
print "SELECT Date,SUM(CostUsd) FROM Stats d WHERE d.Date = " + day + " GROUP BY Date"
os.system('mysql -h -sN -u -p -e " + sql + " > /home/output/DateLoop-" + day + ".txt db')
day += one_day
是否有可能将此设置为将SQL作为输入文件并将该日作为字符串传递给该日期?查询可能会变得更加复杂,甚至需要多次查询,这可能会成为尝试以字符串形式传递的问题。
我愿意,只要查询可以采取的日期作为输入,名字具有相同的日期输出文件和命令行的MySQL客户端
答
尝试明确的格式做任何想法和报价结果字符串:
sql = "....WHERE d.Date = '" + date.isoformat() + "' GROUP BY ..."
行情在使用os.system调用是凌乱和重定向看起来很怪异(如果它不是一个错字)
os.system("mysql db -h -sN -u -p -e '" + sql + "' > /home/output/DateLoop-" + day + ".txt")
答
好了,你可以保存mysql的模板QUER在配置文件中y和与ConfigParser解析它:
配置文件将看起来像:
[mysql query configuration]
dbhost =
db =
username = guest
password =
[query template]
template = SELECT Date, SUM(CostUsd).......
或者你可以将其存储到一个单独的文件,然后用标准的开放(文件名阅读).read等 如果您认为查询在未来会变得更加复杂,那么配置文件的方法可能会更易于管理和理解,但这并没有太大区别。
来获得日期作为参数,你可以使用sys.argv中,或图书馆像下面optparse
答
代码可能会帮助你。它并不特别令人兴奋,故意简单。这不是很多程序员解决这个问题的方式,但是没有更多的信息,它似乎满足了你的要求。
我也假设你是python的新手;如果我错了,请随时忽略此帖。
- 允许在命令行上传递数据库凭证,输出目录和日期(开始和结束)。
- 使用子进程来代替os.system。子进程提供了从python调用外部可执行文件的首选机制。此代码使用其中最简单的代码; call(),因为它与os.system()相似
- 使用optparse来处理命令行参数。虽然代码当然更长且更冗长,但您将来可以更容易地对arg处理进行添加和修改。它也很清楚发生了什么(代码总是被读取得比写入的要多得多)。
- 命令行设置仅在执行脚本时运行,因为它位于
__main__
块内。由于脚本的“逻辑”在main()方法中,因此您也可以将其导入并从另一个源提供选项对象(和arg列表)。
如果您不需要在单独的文件中输出每个日期,可以让数据库引擎计算SUM()并按日期对它们进行分组。你会得到一个数据库调用的所有款项,这将更快,可以产生更简单的代码。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import datetime
import os
import subprocess
from optparse import OptionParser
SQL = """SELECT d.Date, SUM(d.CostUsd) FROM Stats d WHERE d.Date = '%s' GROUP BY d.Date"""
def get_stats(options, dateobj):
"""Return statistics for the date of `dateobj`"""
_datestr = dateobj.strftime('%Y-%m-%d')
sql = SQL % _datestr
filepath = os.path.join(options.outdir, 'DateLoop-%s.txt' % _datestr)
return subprocess.call('mysql -h %s -u %s -p -sN -e "%s" db > %s' % (options.dbhost, options.dbuser, sql, filepath), shell=True)
def main(options, args):
""""""
_date = options.startdate
while _date <= options.enddate:
rs = get_stats(options, _date)
_date += datetime.timedelta(days=1)
if __name__ == '__main__':
parser = OptionParser(version="%prog 1.0")
parser.add_option('-s', '--startdate', type='string', dest='startdate',
help='the start date (format: yyyymmdd)')
parser.add_option('-e', '--enddate', type='string', dest='enddate',
help='the end date (format: yyyymmdd)')
parser.add_option('--output', type='string', dest='outdir', default='/home/output/',
help='target directory for output files')
parser.add_option('--dbhost', type='string', dest='dbhost', default='myhost',
help='SQL server address')
parser.add_option('--dbuser', type='string', dest='dbuser', default='dbuser',
help='SQL server user')
options, args = parser.parse_args()
## Process the date args
if not options.startdate:
options.startdate = datetime.datetime.today()
else:
try:
options.startdate = datetime.datetime.strptime('%Y%m%d', options.startdate)
except ValueError:
parser.error("Invalid value for startdate (%s)" % options.startdate)
if not options.enddate:
options.enddate = options.startdate + datetime.timedelta(days=7)
else:
try:
options.enddate = datetime.datetime.strptime('%Y%m%d', options.enddate)
except ValueError:
parser.error("Invalid value for enddate (%s)" % options.enddate)
main(options, args)
使用MySQLdb模块有什么问题? – alberge 2009-08-03 18:29:01