我想学习Python,所以我开始编写我的第一个程序,这是一个电话簿目录。 它可以选择添加姓名和电话号码,删除号码以及搜索号码。 我已经被困在删除部分约2天了,只是无法让它正常工作。我一直在Python IRC和一切,但一直没能弄明白。 基本上,我的程序将数字存储到文件中的列表中。我无法弄清楚如何删除文件中的特定行,但保持文件的其余部分完好无损。有人可以帮帮我吗?
有些人建议,如果我创建一个临时文件,删除该行,然后将原始文件中的剩余行复制到临时文件,将会更容易。然后使用临时文件覆盖原始文件。所以我一直在尝试这个...
if ui == 'remove':
coname = raw_input('What company do you want to remove? ') # company name
f = open('codilist.txt', 'r') # original phone number listing
f1 = open('codilist.tmp', 'a') # open a tmp file
for line in f:
if line.strip() != coname.strip():
for line in f:
f1.write(line)
break # WILL LATER OVERWRITE THE codilist.txt WITH THE TMP FILE
else:
f1.write(line)
else:
print 'Error: That company is not listed.'
f1.close()
f.close()
continue
答案 0 :(得分:3)
我假设您的文件包含类似< name >< whitespace >< number >在每一行?如果是这种情况,你可以在if语句中使用类似的东西(不包括错误处理!):
name, num = line.strip().split()
if name != coname.strip():
# write to file
的建议:强>
除非您有某些特定原因要使用自定义格式,否则json的文件格式对于此类任务非常有用。另请注意在这些示例中使用'with'语句,这样可以节省您显式关闭文件的时间。
写信息:
import json
# Somehow build a dict of {coname: num,...}
info = {'companyA': '0123456789', 'companyB': '0987654321'}
with open('codilist.txt', 'w') as f:
json.dump(info, f, indent=4) # Using indent for prettier files
阅读/修改文件:
import json
with open('codilist.txt', 'r+') as f:
info = json.load(f)
# Remove coname
if coname in info:
info.pop(coname)
else:
print 'No record exists for ' + coname
# Add 'companyC'
info['companyC'] = '0112233445'
# Write back to file
json.dump(info, f, indent=4)
这些示例需要python2.6或更高版本。如果您使用的是2.5,那么您将需要这些导入:
import simplejson as json
from __future__ import with_statement
希望有所帮助!
答案 1 :(得分:1)
这是一个非常广泛的重写版本:
所有手机数据都包含在电话簿类中;数据保存在内存中(而不是为每次调用保存和重新加载)
它使用csv模块加载和保存数据
将个别行为变成简短的功能或方法(而不是一大块代码)
命令被抽象为函数调度字典(而不是if / then测试的级联)
这应该更容易理解和维护。
import csv
def show_help():
print('\n'.join([
"Commands:",
" help shows this screen",
" load [file] loads the phonebook (file name is optional)",
" save [file] saves the phonebook (file name is optional)",
" add {name} {number} adds an entry to the phonebook",
" remove {name} removes an entry from the phonebook",
" search {name} displays matching entries",
" list show all entries",
" quit exits the program"
]))
def getparam(val, prompt):
if val is None:
return raw_input(prompt).strip()
else:
return val
class Phonebook(object):
def __init__(self, fname):
self.fname = fname
self.data = []
self.load()
def load(self, fname=None):
if fname is None:
fname = self.fname
try:
with open(fname, 'rb') as inf:
self.data = list(csv.reader(inf))
print("Phonebook loaded")
except IOError:
print("Couldn't open '{}'".format(fname))
def save(self, fname=None):
if fname is None:
fname = self.fname
with open(fname, 'wb') as outf:
csv.writer(outf).writerows(self.data)
print("Phonebook saved")
def add(self, name=None, number=None):
name = getparam(name, 'Company name? ')
number = getparam(number, 'Company number? ')
self.data.append([name,number])
print("Company added")
def remove(self, name=None):
name = getparam(name, 'Company name? ')
before = len(self.data)
self.data = [d for d in self.data if d[0] != name]
after = len(self.data)
print("Deleted {} entries".format(before-after))
def search(self, name=None):
name = getparam(name, 'Company name? ')
found = 0
for c,n in self.data:
if c.startswith(name):
found += 1
print("{:<20} {:<15}".format(c,n))
print("Found {} entries".format(found))
def list(self):
for c,n in self.data:
print("{:<20} {:<15}".format(c,n))
print("Listed {} entries".format(len(self.data)))
def main():
pb = Phonebook('phonebook.csv')
commands = {
'help': show_help,
'load': pb.load,
'save': pb.save,
'add': pb.add,
'remove': pb.remove,
'search': pb.search,
'list': pb.list
}
goodbyes = set(['quit','bye','exit'])
while True:
# get user input
inp = raw_input("#> ").split()
# if something was typed in
if inp:
# first word entered is the command; anything after that is a parameter
cmd,args = inp[0],inp[1:]
if cmd in goodbyes:
# exit the program (can't be delegated to a function)
print 'Goodbye.'
break
elif cmd in commands:
# "I know how to do this..."
try:
# call the appropriate function, and pass any parameters
commands[cmd](*args)
except TypeError:
print("Wrong number of arguments (type 'help' for commands)")
else:
print("I didn't understand that (type 'help' for commands)")
if __name__=="__main__":
main()
答案 2 :(得分:0)
像这样简单的东西将读取所有f
,并写出所有不匹配的行:
for line in f:
if line.strip() != coname.strip():
f1.write(line)
答案 3 :(得分:0)
Ned的回答看起来应该有效。如果您还没有尝试过,可以在相关行上方设置python的交互式调试器。然后,您可以打印出line.strip()
和coname.strip()
的值,以验证您是在比较苹果与苹果。
for line in f:
import pdb
pdb.set_trace()
if line.strip() != coname.strip():
f1.write(line)
答案 4 :(得分:0)
您可能不希望以追加('a')模式打开临时文件:
f1 = open('codilist.tmp', 'a') # open a tmp file
另外,请注意
for line in f:
...
f1.write(line)
会在没有换行符的情况下将所有内容写入文件。
您想要的基本结构是:
for line in myfile:
if not <line-matches-company>:
tmpfile.write(line + '\n') # or print >>tmpfile, line
你必须实现<line-matches-company>
(问题中没有足够的信息来知道它应该是什么 - 也许你从数据文件中显示了几行......?)
答案 5 :(得分:0)
我得到了这个......
if ui == 'remove':
coname = raw_input('What company do you want to remove? ') # company name
f = open('codilist.txt')
tmpfile = open('codilist.tmp', 'w')
for line in f:
if coname in line:
print coname + ' has been removed.'
else:
tmpfile.write(line)
f.close()
tmpfile.close()
os.rename('codilist.tmp', 'codilist.txt')
continue