0

私はcsvから値を取得してデータベースに入れようとしていますが、これは大きな問題なく実行できます。

ただし、csvに書き戻す必要があることはわかっているので、次にスクリプトを実行すると、csvファイルのマークの下からDBに値が入力されるだけです。

システム上のCSVファイルは24時間ごとに自動的にフラッシュされるため、csvにマークがない可能性があることに注意してください。したがって、マークが見つからない場合は、基本的にすべての値をデータベースに入れます。

このスクリプトを30分ごとに実行することを計画しているので、csvファイルに48個のマークが含まれている可能性があります。または、マークを削除して毎回ファイルの下に移動することもできますか?

私はファイルを削除してからスクリプトでファイルを再作成しているので、スクリプトが実行されるたびに新しいファイルが作成されますが、これはシステムを何らかの形で破壊するため、優れたオプションではありません。

皆さんがお役に立てば幸いです。

ありがとうございました

Pythonコード:

import csv
import MySQLdb

mydb = MySQLdb.connect(host='localhost',
user='root',
passwd='******',
db='kestrel_keep')

cursor = mydb.cursor()

csv_data = csv.reader(file('data_csv.log'))

for row in csv_data:

    cursor.execute('INSERT INTO `heating` VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,)',
   row)
#close the connection to the database.
mydb.commit()
cursor.close()
import os


print "Done"

私のCSVファイル形式:

2013-02-21,21:42:00,-1.0,45.8,27.6,17.3,14.1,22.3,21.1,1,1,2,2
2013-02-21,21:48:00,-1.0,45.8,27.5,17.3,13.9,22.3,20.9,1,1,2,2
4

3 に答える 3

2

MySQLテーブルの最初のフィールドは一意のタイムスタンプのようです。フィールドが一意である必要があるようにMySQLテーブルを設定し、INSERTその一意性プロパティに違反するsを無視することができます。mysql>プロンプトで、次のコマンドを入力します。

ALTER IGNORE TABLE heating ADD UNIQUE heatingidx (thedate, thetime)    

(日付と時刻を保持している列の名前を変更thedateします。)thetime


データベースにこの変更を加えたら、MySQLに重複挿入を無視させるために、プログラムの1行を変更するだけで済みます。

cursor.execute('INSERT IGNORE INTO `heating` VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,)', row)

INSERT IGNORE ...はい、すでに処理された回線で実行するのは少し無駄ですが、データの頻度(6分ごと?)を考えると、パフォーマンスの観点からはそれほど重要ではありません。

この方法の利点は、テーブルに誤って重複を挿入することが不可能になることです。また、プログラムのロジックをシンプルで読みやすくします。

また、2つのプログラムが同じCSVファイルに同時に書き込むことを回避します。プログラムが通常エラーなしで成功したとしても、プログラムと他のプログラムが同時にファイルに書き込もうとすることがよくあります。これにより、エラーやデータの破損が発生する可能性があります。


cursor.executemany次の代わりにを使用して、プログラムを少し速くすることもできますcursor.execute

rows = list(csv_data)
cursor.executemany('''INSERT IGNORE INTO `heating` VALUES
    ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,)''', rows)

と同等です

for row in csv_data:    
    cursor.execute('INSERT INTO `heating` VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,)',
   row)

ただし、すべてのデータを1つのコマンドにパックします。

于 2013-02-25T10:23:26.323 に答える
1

CSVファイルに「マークを付ける」よりも、処理した最後の行の番号を保存してファイルを保持する方がよいと思います。

したがって、ファイルが存在しない場合(最後に処理された行の番号を保存した場合)、CSVファイル全体を処理します。このファイルが存在する場合は、この行以降のレコードのみを処理します。

作業システムに関する最終コード:

#!/usr/bin/python
import csv
import MySQLdb
import os

mydb = MySQLdb.connect(host='localhost',
user='root',
passwd='*******',
db='kestrel_keep')

cursor = mydb.cursor()

csv_data = csv.reader(file('data_csv.log'))

start_row = 0

def getSize(fileobject):
fileobject.seek(0,2) # move the cursor to the end of the file
size = fileobject.tell()
return size

file = open('data_csv.log', 'rb')
curr_file_size = getSize(file)

# Get the last file Size
if os.path.exists("file_size"):
with open("file_size") as f:
    saved_file_size = int(f.read())


# Get the last processed line
if os.path.exists("lastline"):
with open("lastline") as f:
    start_row = int(f.read())


if curr_file_size < saved_file_size: start_row = 0

cur_row = 0
for row in csv_data:
 if cur_row >= start_row:
     cursor.execute('INSERT INTO `heating` VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s,    %s, %s, %s, %s, %s, %s, %s ,%s)', row)

     # Other processing if necessary

 cur_row += 1

 mydb.commit()
 cursor.close()


# Store the last processed line
with open("lastline", 'w') as f:
start_line = f.write(str(cur_row + 1)) # you want to start at the **next** line
                                      # next time
# Store Current  File Size To Find File Flush    
with open("file_size", 'w') as f:
start_line = f.write(str(curr_file_size))

# not necessary but good for debug
print (str(cur_row))



 print "Done"

編集: ZeroGによって提出され、現在システムで動作している最終コード!! 助けてくれてありがとうXion345

于 2013-02-25T10:15:09.860 に答える
1

各csv行にはタイムスタンプが含まれているようです。これらが常に増加している場合は、すでに記録されている最大タイムスタンプをデータベースに照会し、csvを読み取るときにその時間より前のすべての行をスキップできます。

于 2013-02-25T10:18:55.703 に答える