2009-08-03 73 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)