簡體   English   中英

使用Python 3更新CSV文件(添加/刪除行)

[英]Updating CSV file (add/remove rows) with Python 3

大家好,

我有一個Raspberry Pi系統,可以跟蹤各種用戶正在檢查的工具。 我進行了設置,以便在用戶簽入時以及簽出時執行系統掃描。 通過比較兩次掃描,我可以確定是否已經采取/返回工具。 但是,我還有一個Log.csv文件,用於跟蹤當前檢出的工具。 我可以在檢出工具時添加到此日志中(這里沒有問題),但是在返回工具時我無法刪除該行。

我搜索過SO以尋求解決方案,但沒有找到任何具體的解決方案。 根據我的理解,您無法從CSV文件中刪除單行? 我將不得不重寫該文件,該特定行被省略?

這是我到目前為止所做的,包括在Log.csv文件中添加和刪除行:

with open('Log.csv', 'a+') as f:
    reader = csv.reader(f)
    if tools_taken not in reader:
        csv.writer(open('Log.csv', 'a+')).writerow([tools_taken])

with open('Log.csv', 'a+') as f:
    reader = csv.reader(f)
    if tools_returned in reader:
        ???

請記住,上面的代碼已經過簡化,以保持簡潔。 我認為“如果工具在閱讀器中退回”行太模糊了。 我可能會改為:

for row in reader:
    for field in row:
        if field == tools_taken:
            ???

我是在正確的軌道上嗎? 這里的任何輸入將非常感謝!

根據我的理解,您無法從CSV文件中刪除單行? 我將不得不重寫該文件,該特定行被省略?

究竟。 事實上,對於一般的文件來說也是如此。 為了從文件中間刪除東西,你必須向上移動文件的其余部分,然后截斷留下的殘骸。 您通常不想這樣做,因此csv模塊無法幫助您。


那么,如何創建新的CSV文件? 三種方式:

  1. 在讀取模式下打開,讀取整個文件,關閉,打開寫入模式,寫出整個文件,關閉。
  2. 重命名為Log.csv.bak ,在讀取模式下打開,在寫入模式下打開Log.csv ,然后從一個復制到另一個。
  3. 在讀取模式下打開Log.csv ,以寫入模式打開臨時文件,從一個復制到另一個,然后將臨時文件原子重命名為Log.csv

第三個通常是最好的 - 但不幸的是,很難以跨平台的方式,甚至只是為了Windows。 (但是,如果你只關心Unix,這很容易。)所以,我將展示第二個:

os.rename('Log.csv', 'Log.csv.bak')
with open('Log.csv.bak') as infile, open('Log.csv', 'w') as outfile:
    reader = csv.reader(infile)
    writer = csv.writer(outfile)
    for row in reader:
        if not supposed_to_be_removed(row):
            writer.writerow(row)

而已。


這類似於編寫復制算法代替簡單列表的變異算法的方式:

newlist = [row for row in oldlist if not supposed_to_be_removed(row)]

當然你可以用迭代器而不是列表來編寫它:

newlist = (row for row in oldlist if not supposed_to_be_removed(row))

事實上,你可以在這里使用完全相同的迭代器:

os.rename('Log.csv', 'Log.csv.bak')
with open('Log.csv.bak') as infile, open('Log.csv', 'w') as outfile:
    reader = csv.reader(infile)
    writer = csv.writer(outfile)
    newrows = (row for row in reader if not_supposed_to_be_removed(row))
    writer.writerows(newrows)

如果你願意,你甚至可以把它變成一個單行程:

    writer.writerows(row for row in reader if not supposed_to_be_removed(row))

最后,可能值得考慮一下csv文件是否真的是正確答案。 如果你正在做一大堆操作,不斷重讀和重復寫文件將會很痛苦 - 而且速度很慢。 也許你可以將它保存在內存中,只需讀寫,啟動和關閉,但是你必須確保不丟失錯誤數據。 另見其他選擇。

我不認為csv在這里是正確的結構。 您希望能夠查找給定的工具,找出其tools_taken是否為True,或者更改其tools_taken ,或從文件中刪除工具,或者將工具添加到文件中,對吧?

這就是數據庫的用途,例如shelve

import contextlib
import shelve

tools = shelve.open('Log.db', 'c', writeback=True)
with contextlib.closing(tools):
    # Add a tool
    tools['hammer'] = {'name': 'Hammer', 'owner': 'Joe', 'tools_taken': False}
    # Check if a tool is taken
    if tools['screwdriver']['tools_taken']:
        print('The screwdriver is taken!')
    # Change a tool's taken status:
    tools['screwdriver']['tools_taken'] = True
    # Remove a tool
    del tools['jackhammer']

換句話說,你可以就像一個dict (在這種情況下,充滿了dict ),但它在運行中自動持久化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM