G'大家,
我有一个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:
???
我是否在正确的轨道上?这里的任何输入都将非常感谢!
答案 0 :(得分:1)
根据我的理解,您无法从CSV文件中删除单行?我将不得不重写该文件,并忽略该特定行?
完全。事实上,对于一般的文件来说也是如此。为了从文件中间删除东西,你必须向上移动文件的其余部分,然后截断留下的残骸。您通常不想这样做,因此csv
模块无法帮助您完成此操作。
那么,您如何创建新的CSV文件?三种方式:
Log.csv.bak
,在读取模式下打开,在写入模式下打开Log.csv
,然后从一个复制到另一个。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
文件是否真的是正确答案。如果你正在做一大堆操作,不断重读和重复写文件将会很痛苦 - 而且速度很慢。也许你可以将它保存在内存中,只需读写,启动和关闭,但是你必须确保不丢失错误数据。请参阅我的其他答案以获得另一种选择。
答案 1 :(得分:1)
我不认为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
s),但它在运行中自动持久。