Вопрос плохо определен, но при условии, что OP хочет получить результат, показанный в примере DataFrame (то есть не только последняя строка каким-то образом украшена именем файла, но и все строки), вот способ добиться этого. Для этого примера у нас есть только два файла: file1.txt
содержит две строки: «a» и «b», file2.txt
содержит одну строку: «c».
Мы пишем средство чтения файлов, которое возвращает список списков: каждый подсписок содержит имя файла и строку.
import glob
def get_file(filename):
with open(filename) as f:
return [[filename, line.rstrip('\n')] for line in f]
Попробуйте:
m = map(get_file, glob.glob('file*.txt'))
list(m)
Out[]:
[[['file2.txt', 'c']], [['file1.txt', 'a'], ['file1.txt', 'b']]]
Давайте сгладим эти списки, чтобы получить один двумерный массив. Кроме того, вероятно, лучше получить результат, когда файлы отсортированы в алфавитном порядке.
def flatten(m):
return [k for sublist in m for k in sublist]
m = map(get_file, sorted(glob.glob('file*.txt')))
flatten(m)
Out[]:
[['file1.txt', 'a'], ['file1.txt', 'b'], ['file2.txt', 'c']]
Теперь иногда полезно иметь номер строки (например, если мы собираемся поместить эти данные в DataFrame и выполнить дальнейшую сортировку и аналитику). Наш читатель становится:
def get_file(filename):
with open(filename) as f:
return [[filename, lineno, line.rstrip('\n')] for lineno, line in enumerate(f, start=1)]
m = map(get_file, sorted(glob.glob('file*.txt')))
out = pd.DataFrame(flatten(m), columns=['filename', 'lineno', 'line'])
out
Out[]:
filename lineno line
0 file1.txt 1 a
1 file1.txt 2 b
2 file2.txt 1 c
Обратите внимание, что map
выше прекрасно подходит для многопоточного чтения, если у нас есть большое количество файлов:
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=4) as pool:
m = pool.map(get_file, sorted(glob.glob('file*.txt')))
out = pd.DataFrame(flatten(m), columns=['filename', 'lineno', 'line'])
out
Out[]:
filename lineno line
0 file1.txt 1 a
1 file1.txt 2 b
2 file2.txt 1 c