with open(file, 'a+') 因为 f 没有追加

with open(file, 'a+') as f is not appending

我有一个函数被重复调用并通过 subprocess 将错误数据写入日志文件,但是,每当将新数据写入文件时,旧数据就会被清除。所以它不会在旧数据上附加任何新数据。

我正在做以下事情:

error_file = '\\some\unc\path\error.log'

class Node:  
    def __init__(self, path, rev):
        self.path = path
        self.rev = rev

    def __hash__(self):
        return hash((self.path, self.rev))

    def __eq__(self, node):
        return (self.path, self.rev) == (node.path, node.rev)

    def __ne__(self, node):
        return not(self == node)

def get_excluded_nodes(excludes_dir):
    nodes = list()
    for root, subdirs, files in os.walk(os.path.dirname(excludes_dir)):
       if 'flagged' in files:
          with open(os.path.join(root, 'flagged')) as f:
             for line in f.readlines():
                 try:
                     comps = line.split(' -a')
                     path = comps[0].strip()
                     rev = comps[1].split(':')[0].strip()
                     Nodes.append(Node(path,rev))
                 except:
                     pass
    return nodes

def export_node(node, path=archive_dir):
    with open(error_file, 'a') as f:
        try:
            comps = node.path.split('/')
            if '.' in comps[len(comps)-1]:
                os.makedirs(os.path.join(archive_dir, '/'.join(comps[:-1])))
            else:
                os.makedirs(os.path.join(archive_dir, node.path))

            subprocess.call(['svn', 'export', os.path.join(some_path, node.path), another_path)], stderr=f)
        except:
            pass


def remove_duplicate_nodes(nodes):
   return set(nodes)

if __name__ == '__main__':
    all_nodes = get_excluded_nodes(os.path.realpath(__file__))
    nodes = remove_duplicate_nodes(all_nodes)
    for node in nodes:
       export_node(node)

为什么这行不通?

试试这个:

with open(error_file, 'a+') as f:
   print([my_program], file=f)

仍然 不是 MVCE:它不是最小的(Node 是做什么的,它如何影响附加到文件?)而且它不完整(哪里是get_excluded_nodes?)。由于它不完整,因此也无法验证。

这个 是一个 MVCE,代码最少,应该 做与您的示例相同的事情,并且工作正常。

import subprocess

def test(filename):
    with open(filename, 'a') as f:
        subprocess.call(['bash', '-c', 'echo $$ >&2'], stderr=f)

if __name__=='__main__':
    for _ in range(2):
        test('stderr.log')

这正是您想要的:

$ python stderr.py 
$ cat stderr.log 
344
345

$ python stderr.py 
$ cat stderr.log 
344
345
366
367

edit 我看到你在 Windows,所以 strace 可能不可用。运气不好,您只需要编写一个实际的 MVCE 即可。


也许 运行 您在 strace 下的原始(真实的,可以正常工作的)脚本,看看有什么不同。作为参考,此脚本显示:

$ strace -f -e trace=open,dup2,lseek,write python stderr.py

open("stderr.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
lseek(3, 0, SEEK_END)                   = 28
strace: Process 567 attached
...
[pid   567] dup2(3, 2)                  = 2 # stderr=f
... libc, locale stuff ...
[pid   567] dup2(2, 1)                  = 1 # >&2
[pid   567] write(1, "567\n", 4)        = 4