Trying to create a CSV file with a file search usi

2020-03-30 05:19发布

问题:

I want to open the main folder containing all files (1), search though the files and only grab any .txt file with "mtn" in the title (2), print a the list of txt files (3) then list the txt files in a csv file, including their full path (4).

I can do (1) through (3) with my current code, however the CSV file that gets produced only contains the last filename, so I think there is something wrong with the order of my loops

mtnpath = r"G:\somepath\"
num_files = 0
for root, dirs, files in os.walk(mtnpath):
    for filename in files:
        if fnmatch.fnmatch(filename, '*mtn*'):
            num_files = num_files + 1
            with open(mtnpath + "/" + "txt_file_list.csv", 'w+', newline='') as f:
                thewriter = csv.writer(f)
                # write the header row
                thewriter.writerow(['Filename', 'Path', ])
                # write the rest of the rows with files and path
                thewriter.writerow([filename, 'Path', ])
            print(filename)
print("The total number of mtn files found was " + str(num_files))

In the console I get a running list of the filenames and the statement at the end with the 565 files found. The CSV file should have all of those files listed but only has the last one.

I tried indenting another for loop under the header:

    for filename in files:
        thewriter.writerow([filename, 'Directory', ])

but that doesn't work either.

回答1:

You're opening the file multiple times in w+ mode (explained here in the documentation), which causes its contents to be truncated each time — so that's why you're only seeing the last one. You actually only need to open the file once, and then can write rows to it as needed.

Here's what I mean:

import csv
import fnmatch
import os

mtn_path = r'G:\somepath'
pattern = '*mtn*'
txt_file_csv_path = os.path.join(mtn_path, 'txt_file_list.csv')

with open(txt_file_csv_path, 'w+', newline='') as f:
    thewriter = csv.writer(f)
    # Write a header row.
    thewriter.writerow(['Filename', 'Path', ])
    num_files = 0

    for root, dirs, files in os.walk(mtn_path):
        for filename in files:
            if fnmatch.fnmatch(filename, pattern):
                num_files += 1
                thewriter.writerow((filename, os.path.join(root, filename)))
                print(filename)

print('The total number of mtn files found was ' + str(num_files))


回答2:

The mode string 'w+' causes any existing contents to be truncated. Perhaps see further python open built-in function: difference between modes a, a+, w, w+, and r+?

You don't want to repeatedly open and close the same file anyway; just open it once outside the main loop, and then write whenever you have something more to write.

(Switching to 'a' instead of 'w+' would fix your code with a minimal change; but you then cause the operating system to do a fair amount of gymnastics to open the file, seek to the end, and close it again for every line you want to write.)