質問するログイン新規登録

質問編集履歴

10

修正

2020/10/08 06:32

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -282,9 +282,7 @@
282
282
  # キューにある先頭データを取り出す
283
283
  msg, args = data.get()
284
284
  print(msg, args)
285
- if msg == "DB-CNCT":
286
- cnct()
287
- elif msg == "DB-INSERT":
285
+ if msg == "DB-INSERT":
288
286
  # データベースとの接続がタイムアウトしていたときのための再接続。
289
287
  con.ping(reconnect=True)
290
288
  # tmpにあるデータをデータベースに保存

9

修正

2020/10/08 06:32

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -205,7 +205,7 @@
205
205
  con.commit()
206
206
  ```
207
207
 
208
- # 質問後追記 変更(2020/10/08 14:37
208
+ # 質問後追記 変更(2020/10/08 14:39
209
209
  ```Python:
210
210
  from datetime import datetime
211
211
  import csv
@@ -298,7 +298,7 @@
298
298
  elif msg == "DB-COMMIT":
299
299
  con.commit()
300
300
  elif msg == "DB-DISCNCT":
301
- discnct(con, cur)
301
+ break
302
302
  else:
303
303
  break
304
304
  discnct(con, cur)

8

修正

2020/10/08 05:39

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -205,7 +205,7 @@
205
205
  con.commit()
206
206
  ```
207
207
 
208
- # 質問後追記 変更(2020/10/08 14:34
208
+ # 質問後追記 変更(2020/10/08 14:37
209
209
  ```Python:
210
210
  from datetime import datetime
211
211
  import csv
@@ -300,8 +300,8 @@
300
300
  elif msg == "DB-DISCNCT":
301
301
  discnct(con, cur)
302
302
  else:
303
+ break
303
- discnct(con, cur)
304
+ discnct(con, cur)
304
- break
305
305
 
306
306
 
307
307
  def close():

7

修正

2020/10/08 05:37

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -300,7 +300,7 @@
300
300
  elif msg == "DB-DISCNCT":
301
301
  discnct(con, cur)
302
302
  else:
303
- discnct(con, cur)
303
+ discnct(con, cur)
304
304
  break
305
305
 
306
306
 

6

修正

2020/10/08 05:34

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -223,7 +223,7 @@
223
223
  con = pymysql.connect(
224
224
  host = "localhost",
225
225
  user = "root",
226
- password = "sh1n@n0pisql",
226
+ password = "root",
227
227
  db = "testdb",
228
228
  charset = "utf8"
229
229
  )

5

修正

2020/10/08 05:34

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -205,7 +205,7 @@
205
205
  con.commit()
206
206
  ```
207
207
 
208
- # 質問後追記 変更(2020/10/08 12:58
208
+ # 質問後追記 変更(2020/10/08 14:34
209
209
  ```Python:
210
210
  from datetime import datetime
211
211
  import csv
@@ -223,7 +223,7 @@
223
223
  con = pymysql.connect(
224
224
  host = "localhost",
225
225
  user = "root",
226
- password = "root",
226
+ password = "sh1n@n0pisql",
227
227
  db = "testdb",
228
228
  charset = "utf8"
229
229
  )
@@ -281,6 +281,7 @@
281
281
  while True:
282
282
  # キューにある先頭データを取り出す
283
283
  msg, args = data.get()
284
+ print(msg, args)
284
285
  if msg == "DB-CNCT":
285
286
  cnct()
286
287
  elif msg == "DB-INSERT":
@@ -299,8 +300,8 @@
299
300
  elif msg == "DB-DISCNCT":
300
301
  discnct(con, cur)
301
302
  else:
303
+ discnct(con, cur)
302
304
  break
303
- time.sleep(0.1)
304
305
 
305
306
 
306
307
  def close():

4

修正

2020/10/08 05:33

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -205,20 +205,20 @@
205
205
  con.commit()
206
206
  ```
207
207
 
208
- # 質問後追記
208
+ # 質問後追記 変更(2020/10/08 12:58)
209
209
  ```Python:
210
210
  from datetime import datetime
211
211
  import csv
212
212
  import pymysql
213
213
  import queue
214
214
  import threading
215
+ import time
215
216
  import tkinter as tk
216
217
 
217
218
  tbl = "testtb"
218
219
  tmp = []
219
220
 
220
221
  def cnct():
221
- global con, cur
222
222
  # データベース接続
223
223
  con = pymysql.connect(
224
224
  host = "localhost",
@@ -229,16 +229,17 @@
229
229
  )
230
230
  cur = con.cursor()
231
231
 
232
+ return con, cur
232
233
 
234
+
233
- def discnct():
235
+ def discnct(con, cur):
234
- global con, cur
235
236
  # データベース切断
236
237
  cur.close()
237
238
  con.close()
238
239
 
239
240
 
240
- def read_and_csvout():
241
+ def read_and_csvout(cur):
241
- global cur, tbl
242
+ global tbl
242
243
  cur.execute("SELECT * FROM " + tbl + ";")
243
244
  results = cur.fetchall()
244
245
  lst = []
@@ -251,8 +252,8 @@
251
252
  writer.writerow(lst[i])
252
253
 
253
254
 
254
- def clear():
255
+ def clear(cur):
255
- global cur, tbl
256
+ global tbl
256
257
  cur.execute("DELETE FROM " + tbl + ";")
257
258
 
258
259
 
@@ -275,34 +276,31 @@
275
276
 
276
277
 
277
278
  def loop(data):
279
+ con, cur = cnct()
278
280
  # キュー監視ループ
279
281
  while True:
280
- # キューにデータが存在したら、順番通りにデータベースへ保存する
281
- while not data.empty():
282
- # キューにある先頭データを取り出す
282
+ # キューにある先頭データを取り出す
283
- msg, args = data.get()
283
+ msg, args = data.get()
284
- if msg == "DB-CNCT":
284
+ if msg == "DB-CNCT":
285
- cnct()
285
+ cnct()
286
- elif msg == "DB-INSERT":
286
+ elif msg == "DB-INSERT":
287
- global cur, con
288
- # データベースとの接続がタイムアウトしていたときのための再接続。
287
+ # データベースとの接続がタイムアウトしていたときのための再接続。
289
- con.ping(reconnect=True)
288
+ con.ping(reconnect=True)
290
- # tmpにあるデータをデータベースに保存
289
+ # tmpにあるデータをデータベースに保存
291
- cur.execute("INSERT INTO " + tbl + " VALUES(%s,%s,%s);", (args[0], args[1], args[2]))
290
+ cur.execute("INSERT INTO " + tbl + " VALUES(%s,%s,%s);", (args[0], args[1], args[2]))
292
- elif msg == "CSV-OUTPUT":
291
+ elif msg == "CSV-OUTPUT":
293
- global cur, con
294
- # データベースとの接続がタイムアウトしていたときのための再接続。
292
+ # データベースとの接続がタイムアウトしていたときのための再接続。
295
- con.ping(reconnect=True)
293
+ con.ping(reconnect=True)
296
- read_and_csvout()
294
+ read_and_csvout(cur)
297
- clear()
295
+ clear(cur)
298
- con.commit()
296
+ con.commit()
299
- elif msg == "DB-COMMIT":
297
+ elif msg == "DB-COMMIT":
300
- global con
301
- con.commit()
298
+ con.commit()
302
- elif msg == "DB-DISCNCT":
299
+ elif msg == "DB-DISCNCT":
303
- discnct()
300
+ discnct(con, cur)
304
- else:
301
+ else:
305
- break
302
+ break
303
+ time.sleep(0.1)
306
304
 
307
305
 
308
306
  def close():
@@ -332,8 +330,6 @@
332
330
  thread = threading.Thread(target=loop, args=(data, ))
333
331
  thread.start()
334
332
 
335
- data.put(("DB-CNCT", None))
336
-
337
333
  # ボタンバインド
338
334
  button1.bind("<ButtonRelease>", pushed1)
339
335
  button2.bind("<ButtonRelease>", pushed2)

3

追加

2020/10/08 03:59

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -203,4 +203,158 @@
203
203
  データベースクリア()
204
204
  # コミット。データベースに変更を加えたらそれを反映させるために必要。
205
205
  con.commit()
206
+ ```
207
+
208
+ # 質問後追記
209
+ ```Python:
210
+ from datetime import datetime
211
+ import csv
212
+ import pymysql
213
+ import queue
214
+ import threading
215
+ import tkinter as tk
216
+
217
+ tbl = "testtb"
218
+ tmp = []
219
+
220
+ def cnct():
221
+ global con, cur
222
+ # データベース接続
223
+ con = pymysql.connect(
224
+ host = "localhost",
225
+ user = "root",
226
+ password = "root",
227
+ db = "testdb",
228
+ charset = "utf8"
229
+ )
230
+ cur = con.cursor()
231
+
232
+
233
+ def discnct():
234
+ global con, cur
235
+ # データベース切断
236
+ cur.close()
237
+ con.close()
238
+
239
+
240
+ def read_and_csvout():
241
+ global cur, tbl
242
+ cur.execute("SELECT * FROM " + tbl + ";")
243
+ results = cur.fetchall()
244
+ lst = []
245
+ for i in range(len(results)):
246
+ tmp = results[i]
247
+ lst.append([ tmp[0], tmp[1], tmp[2] ])
248
+ with open("/home/pi/デスクトップ/data.csv", "a", newline="") as f:
249
+ writer = csv.writer(f, lineterminator="\r\n")
250
+ for i in range(len(lst)):
251
+ writer.writerow(lst[i])
252
+
253
+
254
+ def clear():
255
+ global cur, tbl
256
+ cur.execute("DELETE FROM " + tbl + ";")
257
+
258
+
259
+ def pushed1(e):
260
+ global data
261
+ # データベース保存用データをキューに格納
262
+ for i in range(50):
263
+ data.put(("DB-INSERT", [str(i+1), "ButtonPushed1", ""]))
264
+ data.put(("DB-COMMIT", None))
265
+
266
+
267
+ def pushed2(e):
268
+ global data
269
+ # データベース保存用データをキューに格納
270
+ for i in range(50):
271
+ data.put(("DB-INSERT", [str(i+1), "ButtonPushed2", ""]))
272
+ data.put(("DB-COMMIT", None))
273
+ data.put(("CSV-OUTPUT", None))
274
+
275
+
276
+
277
+ def loop(data):
278
+ # キュー監視ループ
279
+ while True:
280
+ # キューにデータが存在したら、順番通りにデータベースへ保存する
281
+ while not data.empty():
282
+ # キューにある先頭データを取り出す
283
+ msg, args = data.get()
284
+ if msg == "DB-CNCT":
285
+ cnct()
286
+ elif msg == "DB-INSERT":
287
+ global cur, con
288
+ # データベースとの接続がタイムアウトしていたときのための再接続。
289
+ con.ping(reconnect=True)
290
+ # tmpにあるデータをデータベースに保存
291
+ cur.execute("INSERT INTO " + tbl + " VALUES(%s,%s,%s);", (args[0], args[1], args[2]))
292
+ elif msg == "CSV-OUTPUT":
293
+ global cur, con
294
+ # データベースとの接続がタイムアウトしていたときのための再接続。
295
+ con.ping(reconnect=True)
296
+ read_and_csvout()
297
+ clear()
298
+ con.commit()
299
+ elif msg == "DB-COMMIT":
300
+ global con
301
+ con.commit()
302
+ elif msg == "DB-DISCNCT":
303
+ discnct()
304
+ else:
305
+ break
306
+
307
+
308
+ def close():
309
+ global data, win, thread
310
+ data.put(("DB-DISCNCT", None))
311
+ thread.join()
312
+ # Tkinterアプリの終了
313
+ win.destroy()
314
+
315
+
316
+ if __name__ == "__main__":
317
+
318
+ # データベースに保存するデータ格納用
319
+ data = queue.Queue()
320
+
321
+ # Tkinter UI
322
+ win = tk.Tk()
323
+
324
+ # ボタン
325
+ button1 = tk.Button(win, text="Button1")
326
+ button1.grid(row=0, column=0, sticky="nsew")
327
+ button2 = tk.Button(win, text="Button2")
328
+ button2.grid(row=0, column=1, sticky="nsew")
329
+
330
+ # データベース操作スレッド
331
+ # ※データベース操作はスレッドセーフではないため、1つのスレッドでのみ操作が可能
332
+ thread = threading.Thread(target=loop, args=(data, ))
333
+ thread.start()
334
+
335
+ data.put(("DB-CNCT", None))
336
+
337
+ # ボタンバインド
338
+ button1.bind("<ButtonRelease>", pushed1)
339
+ button2.bind("<ButtonRelease>", pushed2)
340
+
341
+ # UIクローズ検知
342
+ win.protocol("WM_DELETE_WINDOW", close)
343
+
344
+ # イベントループ
345
+ win.mainloop()
346
+
347
+
348
+ """
349
+ MariaDB [testdb]> DESC testtb;
350
+ +-------+------+------+-----+---------+-------+
351
+ | Field | Type | Null | Key | Default | Extra |
352
+ +-------+------+------+-----+---------+-------+
353
+ | data1 | text | YES | | NULL | |
354
+ | data2 | text | YES | | NULL | |
355
+ | data3 | text | YES | | NULL | |
356
+ +-------+------+------+-----+---------+-------+
357
+ 3 rows in set (0.00 sec)
358
+ """
359
+
206
360
  ```

2

修正

2020/10/08 02:57

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -30,7 +30,7 @@
30
30
  con = pymysql.connect(
31
31
  host = "localhost",
32
32
  user = "root",
33
- password = "sh1n@n0pisql",
33
+ password = "root",
34
34
  db = "testdb",
35
35
  charset = "utf8"
36
36
  )

1

追加

2020/10/08 01:20

投稿

person
person

スコア224

title CHANGED
File without changes
body CHANGED
@@ -177,6 +177,8 @@
177
177
 
178
178
  このときにButton2を押したときの処理が、メインスレッドだとバッファにキューに保存しているだけなのでMySQL操作しているスレッドの動作まで検知できません。
179
179
 
180
+ (グローバル変数で適当なフラグを立てることを考えたのですが、Button1のデータ書き込みが終わったのか、Button2のデータ書き込みが終わったのか、そもそも書き込んでいないのかまではloop()内で区別できないような気がします。変数だけじゃなくコールバック関数などを駆使すればできる?)
181
+
180
182
  どのようにすれば 50,ButtonPushed2 をデータベースに保存した後でCSV出力をすることが可能でしょうか。
181
183
 
182
184
  (ただし、出力データ 50,ButtonPushed2 はあくまでサンプルデータにすぎないので、実際に保存するデータはどうなるか分かりません。そのためスレッドのループ内に下記のような指定をするのはなしでお願いします。)
@@ -194,7 +196,7 @@
194
196
  tmp = data.get()
195
197
  # tmpにあるデータをデータベースに保存
196
198
  cur.execute("INSERT INTO " + tbl + " VALUES(%s,%s,%s);", (tmp[0], tmp[1], tmp[2]))
197
- # データの内容を指定して、CSV出力
199
+ # データの内容を指定して、CSV出力(これは解決策としては×)
198
200
  if tmp == ["50", "ButtonPushed2", ""]:
199
201
  sqldata = データベース読み込み()
200
202
  CSV出力(sqldata)