Python Å‚Ä…czy pliki tekstowe
Mam listę 20 nazw plików, jak ['file1.txt', 'file2.txt', ...]
. Chcę napisać skrypt Pythona, aby połączyć te pliki w nowy plik. Mogłem otworzyć KAŻDY plik przez f = open(...)
, odczytać linię po linii przez wywołanie f.readline()
i zapisać każdą linię do tego nowego pliku. Nie wydaje mi się to zbyt "eleganckie", szczególnie część, w której muszę czytać//pisać wiersz po wierszu.
Czy jest bardziej "elegancki" sposób, aby to zrobić w Pythonie?
11 answers
This should do it
Dla dużych plików:
filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
for fname in filenames:
with open(fname) as infile:
for line in infile:
outfile.write(line)
Dla małych plików:
filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
for fname in filenames:
with open(fname) as infile:
outfile.write(infile.read())
... i jeszcze jeden ciekawy, o którym myślałem :
filenames = ['file1.txt', 'file2.txt', ...]
with open('path/to/output/file', 'w') as outfile:
for line in itertools.chain.from_iterable(itertools.imap(open, filnames)):
outfile.write(line)
Niestety, ta ostatnia metoda pozostawia kilka otwartych deskryptorów plików, którymi i tak powinien zająć się GC. Po prostu myślałem, że to ciekawe
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-16 06:06:39
Użyj shutil.copyfileobj
. Powinno być bardziej wydajne.
with open('output_file.txt','wb') as wfd:
for f in ['seg1.txt','seg2.txt','seg3.txt']:
with open(f,'rb') as fd:
shutil.copyfileobj(fd, wfd, 1024*1024*10)
#10MB per writing chunk to avoid reading big file into memory.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-17 09:03:47
Właśnie do tego służy fileinput:
import fileinput
with open(outfilename, 'w') as fout, fileinput.input(filenames) as fin:
for line in fin:
fout.write(line)
W tym przypadku nie jest to dużo prostsze niż tylko iterowanie plików ręcznie, ale w innych przypadkach posiadanie pojedynczego iteratora, który iterauje wszystkie pliki tak, jakby były pojedynczym plikiem, jest bardzo przydatne. (Również fakt, że fileinput
zamyka każdy plik tak szybko, jak to jest zrobione, oznacza, że nie ma potrzeby with
lub close
każdego z nich, ale to tylko oszczędności w jednej linii, nic wielkiego.)
SÄ… pewne inne sprytne funkcje w fileinput
, takie jak możliwość wprowadzania zmian w plikach poprzez filtrowanie każdej linii.
Jak zaznaczono w komentarzach i omówiono w innym poście, fileinput
dla Pythona 2.7 nie będzie działać zgodnie ze wskazaniami. Tutaj niewielka modyfikacja, aby kod Python 2.7 zgodny
with open('outfilename', 'w') as fout:
fin = fileinput.input(filenames)
for line in fin:
fout.write(line)
fin.close()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-23 08:27:14
Nie znam się na elegancji, ale to działa:
import glob
import os
for f in glob.glob("file*.txt"):
os.system("cat "+f+" >> OutFile.txt")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-03 01:39:23
Co jest nie tak z poleceniami Uniksa ? (biorąc pod uwagę, że nie działa na Windows):
ls | xargs cat | tee output.txt
wykonuje zadanie (możesz wywołać je z Pythona z podprocesem, jeśli chcesz)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-28 20:00:34
Jeśli pliki nie są gigantyczne:
with open('newfile.txt','wb') as newf:
for filename in list_of_files:
with open(filename,'rb') as hf:
newf.write(hf.read())
# newf.write('\n\n\n') if you want to introduce
# some blank lines between the contents of the copied files
Jeśli pliki są zbyt duże, aby mogły być całkowicie odczytane i przechowywane w pamięci RAM, algorytm musi być nieco inny, aby odczytać każdy plik do skopiowania w pętli przez kawałki o stałej długości, na przykład za pomocą read(10000)
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-28 20:04:38
Jeśli masz wiele plików w katalogu, to glob2
może być lepszą opcją do generowania listy nazw plików, zamiast pisania ich ręcznie.
import glob2
filenames = glob2.glob('*.txt') # list of all .txt files in the directory
with open('outfile.txt', 'w') as f:
for file in filenames:
with open(file) as infile:
f.write(infile.read()+'\n')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-06 10:34:57
outfile.write(infile.read()) 2.1085190773010254s
shutil.copyfileobj(fd, wfd, 1024*1024*10) 0.60599684715271s
Prosty benchmark pokazuje, że szutil działa lepiej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 08:10:36
Zobacz teżmetoda read () obiektu File:
Http://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects
Możesz zrobić coś takiego:
concat = ""
for file in files:
concat += open(file).read()
Lub bardziej "elegancki" sposób python:
concat = ''.join([open(f).read() for f in files])
Które zgodnie z tym artykułem: http://www.skymind.com / ~ ocrow / python_string / również byłby najszybszy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-28 20:04:20
def concatFiles():
path = 'input/'
files = os.listdir(path)
for idx, infile in enumerate(files):
print ("File #" + str(idx) + " " + infile)
concat = ''.join([open(path + f).read() for f in files])
with open("output_concatFile.txt", "w") as fo:
fo.write(path + concat)
if __name__ == "__main__":
concatFiles()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-28 00:03:01
Alternatywa dla odpowiedzi @ inspectorG4dget (najlepsza odpowiedź na dzień 29-03-2016). Testowałem z 3 plikami po 436MB.
@inspectorG4dget rozwiÄ…zanie: 162 sekund
Następujące rozwiązanie: 125 sekund
from subprocess import Popen
filenames = ['file1.txt', 'file2.txt', 'file3.txt']
fbatch = open('batch.bat','w')
str ="type "
for f in filenames:
str+= f + " "
fbatch.write(str + " > file4results.txt")
fbatch.close()
p = Popen("batch.bat", cwd=r"Drive:\Path\to\folder")
stdout, stderr = p.communicate()
Chodzi o to, aby utworzyć plik wsadowy i wykonać go, wykorzystując "starą dobrą technologię". Jego pół-python, ale działa szybciej. Działa na windows.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 02:23:12