亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 Python 中停止程序并保存數據的最佳方法是什么?

在 Python 中停止程序并保存數據的最佳方法是什么?

青春有我 2023-09-26 17:26:07
我對在 Python 中運行的程序不感興趣,當然,control c 可以做到這一點。我感興趣的是以下情況:假設您有一個運行 5 小時的程序。您讓它運行了兩個小時,但隨后決定您到目前為止所做的事情值得保存,但您仍然不想繼續。那么保存數據并退出程序的最佳方法是什么?到目前為止,我所做的是將布爾值存儲在 pickle 中,然后用每個循環打開 pickle 并檢查其值。如果布爾值為 true,則程序繼續運行,如果為 false,則程序停止并保存數據并退出。我可以使用不同的程序更改布爾值。然而,即使 pickle 僅由一個布爾值組成,它仍然會嚴重減慢程序速度,可能會慢 10 倍,因為泡菜需要很長時間才能打開。我考慮過其他解決方案,并且我知道 pdb_trace() 工具,但我真的不知道如何在這種情況下使用它。我想也許設置環境變量可能會有所幫助,但我不太擅長設置環境變量。任何建議,將不勝感激。
查看完整描述

2 回答

?
慕容3067478

TA貢獻1773條經驗 獲得超3個贊

答案包括檢查環境中的變量和文件等內容。這些都可以,但是你可以這樣做嗎:


try:

  main()

except KeyboardInterrupt:

  save()

或者,如果保存過程與 main 完成后使用的過程相同,則更穩健的策略是


try:

  main()

finally:

  save()

在這里,save()將運行任何錯誤KeyboardInterrupt 或其他情況。如果成功的話它也會運行main()。


如果您嘗試使用單獨的程序關閉它,則可以發送信號。


查看完整回答
反對 回復 2023-09-26
?
繁花不似錦

TA貢獻1851條經驗 獲得超4個贊

對于您有趣的任務,只是為了好玩,我決定實現相當復雜但通用的解決方案來異步處理任何命令。命令在文件中提供cmds.txt,每行單個命令。目前僅支持兩個命令save和??崭窈罂赡馨诙€可選參數,要保存到的文件名(默認為)。exitsavesave.txt

如果程序異常退出(未exit提供命令),則工作將保存到臨時文件中save.txt.tmp。

cmds.txt文件在單獨的線程中處理,每秒檢查一次文件,檢查速度非??煲虼瞬徽加肅PU,檢查只是測試文件修改時間是否已更改。每個新命令都應添加到新行的文件末尾,不應刪除已處理的行。在程序啟動命令文件被清理。

主線程只檢查has_cmdsbool 變量(如果有新命令),它非??觳⑶铱梢越洺M瓿桑缭谔幚碜钚〉娜蝿眨ㄈ?10-20 毫秒)之后。沒有互斥體,因此一切都運行得非??臁?/p>

例如使用主線程在隨機時間點生成任務處理結果并將結果存儲到數組中。在保存命令中,此結果數組將保存為 JSON。

程序將有關其所做操作的所有信息打印到控制臺中,并包含時間戳。

要測試程序,請執行以下操作:

  1. 啟動程序。它立即開始處理計算工作。

  2. 在任何文本編輯器中打開cmds.txt

  3. 添加帶有save字符串的新行。保存存檔。

  4. 程序應打印該save命令已被識別、處理并且工作已保存到文件save.txt

  5. 在編輯器中添加另一行save other.txt。保存存檔

  6. 程序應該打印它已將工作保存到save.txt

  7. 添加新行exit并保存。

  8. 程序應該退出。

  9. 再次嘗試運行程序。

  10. 嘗試按Ctrl+C程序控制臺。

  11. 程序應該捕獲此鍵盤中斷并說明這一點,并將工作保存到臨時文件save.txt.tmp并退出程序。


import threading, random, os, json, time, traceback


cmds = []

has_cmds = False

cmds_fname = 'cmds.txt'

save_fname = 'save.txt'

save_fname_tmp = 'save.txt.tmp'


def CurTimeStr(*, exact = False):

? ? from datetime import datetime

? ? return (datetime.now(), datetime.utcnow())[exact].strftime(('[%H:%M:%S]', '[%Y-%m-%d %H:%M:%S.%f UTC]')[exact])


def Print(*pargs, **nargs):

? ? print(CurTimeStr(), *pargs, flush = True, **nargs)

? ??

def AddCmd(c, *, processed = False):

? ? global cmds, has_cmds

? ? cmds.append({**{'processed': threading.Event()}, **c})

? ? if processed:

? ? ? ? cmds[-1]['processed'].set()

? ? has_cmds = True

? ? return cmds[-1]


def ExternalCommandsThread():

? ? global cmds, has_cmds

? ? Print('Cmds thread started.')

? ? first, next_line, mtime = True, 0, 0.

? ? while True:

? ? ? ? try:

? ? ? ? ? ? if first:

? ? ? ? ? ? ? ? Print(f'Cleaning cmds file "{cmds_fname}".')

? ? ? ? ? ? ? ? with open(cmds_fname, 'wb') as f:

? ? ? ? ? ? ? ? ? ? pass

? ? ? ? ? ? ? ? first = False

? ? ? ? ? ? if os.path.exists(cmds_fname) and abs(os.path.getmtime(cmds_fname) - mtime) > 0.0001 and os.path.getsize(cmds_fname) > 0:

? ? ? ? ? ? ? ? Print(f'Updated cmds file "{cmds_fname}". Processing lines starting from {next_line + 1}.')

? ? ? ? ? ? ? ? with open(cmds_fname, 'r', encoding = 'utf-8-sig') as f:

? ? ? ? ? ? ? ? ? ? data = f.read()

? ? ? ? ? ? ? ? lines = list(data.splitlines())

? ? ? ? ? ? ? ? try:

? ? ? ? ? ? ? ? ? ? mtime = os.path.getmtime(cmds_fname)

? ? ? ? ? ? ? ? ? ? for iline, line in zip(range(next_line, len(lines)), lines[next_line:]):

? ? ? ? ? ? ? ? ? ? ? ? line = line.strip()

? ? ? ? ? ? ? ? ? ? ? ? if not line:

? ? ? ? ? ? ? ? ? ? ? ? ? ? continue

? ? ? ? ? ? ? ? ? ? ? ? if line[0] not in ['[', '{', '"']:

? ? ? ? ? ? ? ? ? ? ? ? ? ? cmd = line.split()

? ? ? ? ? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? ? ? ? ? cmd = json.loads(line)

? ? ? ? ? ? ? ? ? ? ? ? pargs = []

? ? ? ? ? ? ? ? ? ? ? ? if type(cmd) is list:

? ? ? ? ? ? ? ? ? ? ? ? ? ? cmd, *pargs = cmd

? ? ? ? ? ? ? ? ? ? ? ? cmd = {'cmd': cmd, 'pargs': pargs}

? ? ? ? ? ? ? ? ? ? ? ? assert 'cmd' in cmd, 'No "cmd" in command line!'

? ? ? ? ? ? ? ? ? ? ? ? c = cmd['cmd']

? ? ? ? ? ? ? ? ? ? ? ? if c in ['save']:

? ? ? ? ? ? ? ? ? ? ? ? ? ? assert len(set(cmd.keys()) - {'cmd', 'fname', 'pargs'}) == 0

? ? ? ? ? ? ? ? ? ? ? ? ? ? AddCmd({'cmd': 'save', 'fname': cmd.get('fname', (cmd['pargs'] or [save_fname])[0])})

? ? ? ? ? ? ? ? ? ? ? ? elif c == 'exit':

? ? ? ? ? ? ? ? ? ? ? ? ? ? AddCmd({'cmd': 'exit'})

? ? ? ? ? ? ? ? ? ? ? ? else:

? ? ? ? ? ? ? ? ? ? ? ? ? ? assert False, f'Unrecognized cmd "{c}"!'

? ? ? ? ? ? ? ? ? ? ? ? Print(f'Parsed cmd "{c}" on line {iline + 1}.')

? ? ? ? ? ? ? ? ? ? ? ? next_line = iline + 1

? ? ? ? ? ? ? ? except (json.decoder.JSONDecodeError, AssertionError) as ex:

? ? ? ? ? ? ? ? ? ? traceback.print_exc()

? ? ? ? ? ? ? ? ? ? Print(f'Failed to parse cmds line {iline + 1} with text "{line}"!')

? ? ? ? ? ? ? ? except:

? ? ? ? ? ? ? ? ? ? raise

? ? ? ? ? ? for i, c in enumerate(cmds):

? ? ? ? ? ? ? ? if c is None:

? ? ? ? ? ? ? ? ? ? continue

? ? ? ? ? ? ? ? if not c['processed'].is_set():

? ? ? ? ? ? ? ? ? ? has_cmds = True

? ? ? ? ? ? ? ? while not c['processed'].wait(10):

? ? ? ? ? ? ? ? ? ? Print(f'Timed out waiting for cmd "{c["cmd"]}" to be processed, continuing waiting!')

? ? ? ? ? ? ? ? Print(f'Processed cmd "{c["cmd"]}".')

? ? ? ? ? ? ? ? cmds[i] = None

? ? ? ? ? ? ? ? if c['cmd'] == 'exit':

? ? ? ? ? ? ? ? ? ? Print('Exit cmd. Cmds thread finishes.')

? ? ? ? ? ? ? ? ? ? return

? ? ? ? ? ? has_cmds = False

? ? ? ? ? ? time.sleep(1)

? ? ? ? except Exception as ex:

? ? ? ? ? ? traceback.print_exc()

? ? ? ? ? ? Print(f'Exception ^^^^^ in Cmds thread!')

? ? ? ? ? ? AddCmd({'cmd': 'exit'})

? ? ? ? ? ? time.sleep(3)


def Main():

? ? global cmds, has_cmds

? ??

? ? Print('Main thread started.')

? ??

? ? threading.Thread(target = ExternalCommandsThread, daemon = False).start()

? ??

? ? results = []

? ??

? ? def SaveWork(fname):

? ? ? ? with open(fname, 'w', encoding = 'utf-8') as f:

? ? ? ? ? ? f.write(json.dumps(results, ensure_ascii = False, indent = 4))

? ? ? ? Print(f'Work saved to "{fname}".')

? ? ? ??

? ? def ProcessCmds():

? ? ? ? # Returns False only if program should exit

? ? ? ? for c in cmds:

? ? ? ? ? ? if c is None or c['processed'].is_set():

? ? ? ? ? ? ? ? continue

? ? ? ? ? ? if c['cmd'] == 'save':

? ? ? ? ? ? ? ? SaveWork(c['fname'])

? ? ? ? ? ? elif c['cmd'] == 'exit':

? ? ? ? ? ? ? ? Print('Exit cmd. Main thread finishes...')

? ? ? ? ? ? ? ? c['processed'].set()

? ? ? ? ? ? ? ? return False

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? assert False, 'Unknown cmd "c["cmd"]"!'

? ? ? ? ? ? c['processed'].set()

? ? ? ? return True


? ? try:? ??

? ? ? ? # Main loop of tasks processing

? ? ? ? for i in range(1000):

? ? ? ? ? ? for j in range(10):

? ? ? ? ? ? ? ? if has_cmds and not ProcessCmds(): # Very fast check if there are any commands

? ? ? ? ? ? ? ? ? ? return # Exit

? ? ? ? ? ? ? ? # Emulate small work of 0-200 ms long.

? ? ? ? ? ? ? ? time.sleep(random.random() * 0.2)

? ? ? ? ? ? ? ? # Store results of work in array

? ? ? ? ? ? ? ? results.append({'time': CurTimeStr(exact = True), 'i': i, 'j': j})

? ? ? ? assert False, 'Main finished without exit cmd!'

? ? except BaseException as ex:

? ? ? ? traceback.print_exc()

? ? ? ? Print(f'Exception ^^^^^ in Main thread!')

? ? ? ? SaveWork(save_fname_tmp)

? ? ? ? AddCmd({'cmd': 'exit'}, processed = True)

? ??

if __name__ == '__main__':

? ? Main()

示例輸出 1:


[08:15:16] Main thread started.

[08:15:16] Cmds thread started.

[08:15:16] Cleaning cmds file "cmds.txt".

[08:15:21] Updated cmds file "cmds.txt". Processing lines starting from 1.

[08:15:21] Parsed cmd "save" on line 1.

[08:15:21] Work saved to "save.txt".

[08:15:21] Processed cmd "save".

[08:15:31] Updated cmds file "cmds.txt". Processing lines starting from 2.

[08:15:31] Parsed cmd "save" on line 2.

[08:15:31] Work saved to "other.txt".

[08:15:31] Processed cmd "save".

[08:15:35] Updated cmds file "cmds.txt". Processing lines starting from 3.

[08:15:35] Parsed cmd "exit" on line 3.

[08:15:35] Exit cmd. Main thread finishes...

[08:15:35] Processed cmd "exit".

[08:15:35] Exit cmd. Cmds thread finishes.

與上面的輸出相對應的命令文件cmds.txt:


save

save other.txt

exit

示例輸出 2:


[08:14:39] Main thread started.

[08:14:39] Cmds thread started.

[08:14:39] Cleaning cmds file "cmds.txt".

Traceback (most recent call last):

? File "stackoverflow_64165394_processing_commands_in_prog.py", line 127, in Main

? ? time.sleep(random.random() * 0.2)

KeyboardInterrupt

[08:14:40] Exception ^^^^^ in Main thread!

[08:14:40] Work saved to "save.txt.tmp".

[08:14:41] Processed cmd "exit".

[08:14:41] Exit cmd. Cmds thread finishes.

舉個例子save.txt:


[

? ? {

? ? ? ? "time": "[2020-10-02 05:15:16.836030 UTC]",

? ? ? ? "i": 0,

? ? ? ? "j": 0

? ? },

? ? {

? ? ? ? "time": "[2020-10-02 05:15:16.917989 UTC]",

? ? ? ? "i": 0,

? ? ? ? "j": 1

? ? },

? ? {

? ? ? ? "time": "[2020-10-02 05:15:17.011129 UTC]",

? ? ? ? "i": 0,

? ? ? ? "j": 2

? ? },

? ? {

? ? ? ? "time": "[2020-10-02 05:15:17.156579 UTC]",

? ? ? ? "i": 0,

? ? ? ? "j": 3

? ? },


? ? ................


查看完整回答
反對 回復 2023-09-26
  • 2 回答
  • 0 關注
  • 166 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號