2

我想学习 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
4

6 回答 6

4

我假设您的文件在每一行都包含类似 < 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

希望有帮助!

于 2012-06-22T13:12:48.383 回答
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()
于 2012-06-22T14:02:03.603 回答
0

像这样简单的东西会读取所有的f,并写出所有不匹配的行:

for line in f:
    if line.strip() != coname.strip():
        f1.write(line)
于 2012-06-22T01:08:03.097 回答
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
于 2012-06-24T03:41:45.223 回答
0

内德的回答看起来应该可行。如果您还没有尝试过,您可以在相关行上方设置 python 的交互式调试器。然后你可以打印出 和 的值line.strip()coname.strip()验证你正在比较苹果和苹果。

for line in f:
    import pdb
    pdb.set_trace()
    if line.strip() != coname.strip():
        f1.write(line)

这是 pdb 命令的列表

于 2012-06-22T02:22:21.157 回答
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>(问题中没有足够的信息来知道它应该是什么 - 也许如果你从你的数据文件中显示了几行......?)

于 2012-06-22T08:21:43.753 回答