下面的代碼旨在當一個檔案被添加到其檔案夾中時觸發。如果檔案型別是.csv或.txt,它需要讀取該檔案。起初,我得到的訊息是
Message=[Errno 13] Permission denied: 'TestDataFile2021-09-11_15-54.csv'
當試圖讀取該檔案時。我相信這是因為該檔案夾正被作業執行緒使用。我一直試圖找出一種方法來暫停該執行緒,運行該函式,然后繼續監控該檔案夾。
錯誤:
# Loop the data lines。
with open(data_file, 'r ') as temp_f:
我需要暫停的地方:
if fType == " .csv" or fType == " .txt":
data_file = a_string
thread_pool_executor.submit(self.process_csv) # 暫停執行緒,運行process_csv,然后恢復。
self.process_csv()
完整代碼:
import os
import win32file
import win32event
import win32con
from win32com import client
import ctypes
import pandas as pd
import csv
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
from openpyxl import load_workbook
import wx
import glob
from os.path import splitext
from concurrent import futures
import sys
import time
thread_pool_executor = futures.ThreadPoolExecutor(max_workers=3)
class MainFrame(wx.Frame)。
def __init__(self, parent, title)。
super(MainFrame, self).__init__(parent, title=title,size=(600, 400)
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour("light gray")
#創建尺寸器 #創建尺寸器
vbox = wx.BoxSizer(wx.VERTICAL)
#Create widgets;/span>
st1 = wx.StaticText(self.panel, label='Script is not running.' )
tc = wx.TextCtrl(self.panel)
btn_start = wx.Button(self.panel, label='Run Script', size=(100, 30))
btn_start.SetBackgroundColour(wx.Colour(198, 89, 17)
#self.btn_login.SetFont(self.b_font)。
btn_start.Bind(wx.EVT_BUTTON, self.onStart)
vbox.Add(st1,-1 , wx.ALIGN_CENTRE | wx.ALL, 5)
vbox.Add(btn_start, 0, wx.ALIGN_CENTRE | wx.ALL, 5)
vbox.Add(tc,2, wx.EXPAND| wx.ALL, 10)
#Layout[/span
self.panel.SetSizer(vbox)
self.Centre()
self.Show()
def onStart(self,event)。
print('Listening')
self._quit = False ('Listening')
thread_pool_executor.submit(self.monitor_folder)
thread_pool_executor.submit(self.active_listening)
def process_csv(self)。
data_file = "TestDataFile2021-09-11_15-54.csv"。
data_file_delimiter = ' ,'
largest_column_count = 0
# 回圈資料行
with open(data_file, 'r '/span>) as temp_f:
lines = temp_f.readlines()
for l in lines:
column_count = len(l.split(data_file_delimiter) ) 1
largest_column_count = column_count if largest_column_count < column_count else biggest_column_count
column_names = [i for i in range(0, largest_column_count) ]
# Read csv
df = pd.read_csv(data_file, delimiter=data_file_delimiter, names=column_names) #header=None,/span>
df.fillna("", inplace=True)
print(df)
def active_listening(self)。
m = 'Listening'
i = 1: m = 'Listening'.
while self._quit == False:
time.sleep(2)
if i <= 3:
m = m ".".
print(m)
i = i 1 1
else:
i = 1
m = 'Listening': i = 1.
def monitor_folder(self)。
#wx.CallAfter(self.print1).
while self._quit == False:
path_to_watch = os.path.abspath ("。")
# FindFirstChangeNotification設定了一個用于觀察的手柄。
# 檔案變化。第一個引數是要被的路徑。
# watched; 第二個引數是一個布林值,表示是否# watched。
# 指定目錄下的目錄是否要被監視;
# 第三個是一個標志串列,說明對 # 目錄的哪種改變。
# 監視的。我們只是在看檔案的添加/洗掉情況。
#
change_handle = win32file.FindFirstChangeNotification (
path_to_watch,
0,
win32con.FILE_NOTIFY_CHANGE_FILE_NAME
)
#
# 永遠回圈,列出任何檔案變化。The WaitFor...將
# 每半秒超時一次,允許鍵盤中斷。
# 來終止回圈。
try:
old_path_contents = dict ([(f, None) for f in os.listdir (path_to_watch)] )
while 1:
result = win32event.WaitForSingleObject (change_handle, 500)
# 如果WaitFor...的回傳是因為一個通知(如)。
# 相對于超時或一些錯誤),那么就找
#目錄內容的變化。
if result == win32con.WAIT_OBJECT_0:
new_path_contents = dict ([(f, None) for f in os.listdir (path_to_watch)] )
added = [f for f in new_path_contents if not f in old_path_contents]
deleted = [f for f in old_path_contents if not f in new_path_contents]
if添加。
print ("added: ", ", ".join (added))
#Get file type="/span"。
a_string = ", ".join (added)
length = len(a_string)
fType = a_string[length - 4:]
if fType == ".csv" or fType == ".txt":
data_file = a_string
thread_pool_executor.submit(self.process_csv) # 暫停執行緒,運行process_csv,然后恢復。
self.process_csv()
else:
print('not what we want')
if洗掉。print ("deleted: ", ", ".join (delete))
old_path_contents = new_path_contents
win32file.FindNextChangeNotification (change_handle)
finally:
win32file.FindCloseChangeNotification (change_handle)
def main()。
app = wx.App()
ex = MainFrame(None, title='Border')
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
uj5u.com熱心網友回復:
現在無法運行你的程式,所以這只是一個猜測。
如果確實是你的程式內部存在訪問檔案的競賽條件,你可以通過使用鎖來解決這個問題。
每當你訪問檔案/目錄/其他受保護的資源時,你將用鎖來封裝操作: 重要的部分是確保你的代碼中每一個訪問資源的位置都像這樣被封裝起來。這可以確保在任何特定時間只有一個執行緒可以訪問該資源。如果一個執行緒在被另一個執行緒持有時試圖獲取鎖,那么這個嘗試就會阻塞,只有在另一個執行緒釋放鎖時才會繼續進行。
如果問題是一個競賽條件與外部源,那么這將不起作用。如果一個外部程式創建了你的程式試圖讀取的那些檔案,你的作業系統可能會保護該檔案,同時被其他行程保持開放寫入,不允許你訪問它。在這種情況下,正確的方法是捕捉例外,等待一小會兒再試,一直試到成功為止。
uj5u.com熱心網友回復: 我能夠想出一個解決方法。當另一個執行緒在同一個檔案夾中與Win32互動時,你似乎不能與一個檔案互動。
這一點: 被替換成:
標籤:from threading import Lock
....
foo = Lock() #this is a global level variable。
with foo:
with open(data_file, 'r '/span>) as temp_f:
...
data_file = "TestDataFile2021-09-11_15-54.csv"
data_file_delimiter = ' ,'
largest_column_count = 0
#with FileLock('TestDataFile2021-09-11_15-54.csv'):
#with thread_lock:。
#Loop the data lines。
with open(data_file, 'r ') as temp_f:
lines = temp_f.readlines()
for l in lines:
column_count = len(l.split(data_file_delimiter) ) 1
largest_column_count = column_count if largest_column_count < column_count else biggest_column_count
column_names = [i for i in range(0, largest_column_count-1) ]
# 讀取csv[/span
df = pd.read_csv(data_file, delimiter=data_file_delimiter, names=column_names) #header=None, #, names=column_names
df.fillna("", inplace=True)
df.set_index(0, inplace = True)
df = pd.read_fwf('TestDataFile2021-09-11_15-54.csv', header=None)
df = df[0].str.split(', ', expand=True)
df.set_index(0, inplace = True)
df.fillna("", inplace=True)
