如何在Python中使用变量名打开一个或多个文件?

0 投票
3 回答
599 浏览
提问于 2025-04-16 16:24

我是一个Python新手,第一次在这里发帖...

我正在制作一个大规模磁盘复制程序,之前遇到的问题都解决得不错。现在我想根据用户选择的复选框,打开1到n(最多28个)个文件(实际上是在Linux中的驱动器,比如/dev/sdc、/dev/sdd等)。

我用的代码大概是这样的,但在执行到eval那一行时,出现了“不能给函数调用赋值”的错误。这不是我实际的代码,只是模拟了我的问题,请忽略文件路径。

有什么合适的方法可以做到这一点呢?

#!/usr/bin/env python

class snippet:
    def __init__(self):
        # open files for binary writing
        file_in = open('/dev/null', 'rb')
        ints = [0, 1, 2, 3]
        for i in ints:
            num = str(i)
                eval('f_out' + num) = open('/tmp/tmp' + num, 'wb') 

        # READ/WRITE CODE GOES HERE 

        # close files
        file_in.close()
        for i in ints:
            num = str(i)
            print "Number: " + num
            eval("f_out" + num).close() 

if __name__ == '__main__':
    app = snippet()

谢谢,
罗伊

3 个回答

1

与其使用 eval() 来创建一堆有名字的文件对象(每次想对其中一个操作时都得再用 eval()),不如把它们都存储在一个或多个列表里,甚至可以把输入文件也放进去,然后根据需要进行处理。这样做有几个好处:首先,你可以很方便地对这些文件对象进行统一操作,还可以轻松改变它们的数量。例如:

class Snippet:
    NUM_OUTPUT_FILES = 4
    FILE_NAMES = (['/dev/null'] +
                  ['/tmp/tmp%d' % n for n in xrange(NUM_OUTPUT_FILES)])
    def __init__(self):
        # open all the files
        self.files = ([open(self.FILE_NAMES[0], 'rb')] +
                       map(lambda fname: open(fname, 'wb'), self.FILE_NAMES[1:]))
    def run(self):
        # READ/WRITE CODE GOES HERE
        # for example
        # data = self.files[0].read(1024)
        # self.files[1].write(data)
        # data = self.files[0].read(1024)
        # self.files[3].write(data)

        # close all files opened
        map(file.close, self.files)

if __name__ == '__main__':
    app = Snippet()
    app.run()

 

2

你可以用一个包含file对象的列表来实现这个功能。一般来说,使用eval被认为是不太好的做法。无论如何,在你的程序中使用eval都是不正确的。不过,你可以用exec来做同样的事情,但这也不推荐。

exec("f_out%d = open('%s%d', 'wb')" % (num, "/tmp/tmp", num))

你应该使用类似这样的东西:

open_files = []
num = 4
for i in range(num):
    open_files.append(open("/tmp/tmp" + i, 'wb'))
6

不要使用eval;应该保持一个字典(编辑:或者列表)来存储文件句柄,而不是使用单独命名的变量。

#!/usr/bin/env python

def main():
    outfiles = [open("/tmp/tmp{0}".format(i), 'wb') for i in (0,1,2,3)]

    with open('/dev/null', 'rb') as inf:
        # do reading/writing
        pass

    for i,f in enumerate(outfiles):
        print("Closing number {0}".format(i))
        f.close()

if __name__ == '__main__':
    main()

撰写回答