2009-08-03 174 views
1

我试图将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客户端

+0

使用MySQLdb模块有什么问题? – alberge 2009-08-03 18:29:01

回答

1

尝试明确的格式做任何想法和报价结果字符串:

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") 
0

好了,你可以保存mysql的模板QUER在配置文件中y和与ConfigParser解析它:

配置文件将看起来像:

[mysql query configuration] 
dbhost = 
db = 
username = guest 
password = 

[query template] 
template = SELECT Date, SUM(CostUsd)....... 

或者你可以将其存储到一个单独的文件,然后用标准的开放(文件名阅读).read等 如果您认为查询在未来会变得更加复杂,那么配置文件的方法可能会更易于管理和理解,但这并没有太大区别。

来获得日期作为参数,你可以使用sys.argv中,或图书馆像下面optparse

3

代码可能会帮助你。它并不特别令人兴奋,故意简单。这不是很多程序员解决这个问题的方式,但是没有更多的信息,它似乎满足了你的要求。

我也假设你是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)