我编写了一个python脚本来处理给定目录中的一组ASCII文件。我想知道是否有更简洁和/或“pythonesque”的方式来做,而不会失去可读性?
import os
import fileinput
import glob
import string
indir='./'
outdir='./processed/'
for filename in glob.glob(indir+'*.asc'): # get a list of input ASCII files to be processed
fin=open(indir+filename,'r') # input file
fout=open(outdir+filename,'w') # out: processed file
lines = iter(fileinput.input([indir+filename])) # iterator over all lines in the input file
fout.write(next(lines)) # just copy the first line (the header) to output
for line in lines:
val=iter(string.split(line,' '))
fout.write('{0:6.2f}'.format(float(val.next()))), # first value in the line has it's own format
for x in val: # iterate over the rest of the numbers in the line
fout.write('{0:10.6f}'.format(float(val.next()))), # the rest of the values in the line has a different format
fout.write('\n')
fin.close()
fout.close()
;;; This line is the header line
-5.0 1.090074154029272 1.0034662411357929 0.87336062116561186 0.78649408279093869 0.65599958665017222 0.4379879132749317 0.26310799350679176 0.087808018565486673
-4.9900000000000002 1.0890770415316042 1.0025480136545413 0.87256100700428996 0.78577373527626004 0.65539842673645277 0.43758616966566649 0.26286647978335914 0.087727357602906453
-4.9800000000000004 1.0880820021223023 1.0016316956763136 0.87176305623792771 0.78505488659611744 0.65479851808106115 0.43718526271594083 0.26262546925502467 0.087646864773454014
-4.9700000000000006 1.0870890372077564 1.0007172884938402 0.87096676998908273 0.78433753775986659 0.65419986152386733 0.4367851929843618 0.26238496225635727 0.087566540188423345
-4.9600000000000009 1.086098148170821 0.99980479337809591 0.87017214936140763 0.78362168975984026 0.65360245789061966 0.4363859610200459 0.26214495911617541 0.087486383957276398
;;; This line is the header line
-5.00 1.003466 0.786494 0.437988 0.087808
-4.99 1.002548 0.785774 0.437586 0.087727
-4.98 1.001632 0.785055 0.437185 0.087647
-4.97 1.000717 0.784338 0.436785 0.087567
-4.96 0.999805 0.783622 0.436386 0.087486
答案 0 :(得分:5)
除了一些细微的变化,由于Python随时间的变化,这看起来很好。
你混合了两种不同风格的next();旧的方式是it.next(),新的是下一个(它)。您应该使用字符串方法split()而不是通过字符串模块(该模块主要用于向后兼容Python 1.x)。没有必要使用通过几乎无用的“fileinput”模块,因为打开文件句柄也是迭代器(该模块来自Python文件处理迭代器之前的时间。)
编辑:正如@codeape所指出的,glob()返回完整路径。如果indir不是“./”,那么你的代码将不起作用。我已经更改了以下内容以使用正确的listdir / os.path.join解决方案。我也比字符串格式更熟悉“%”字符串插值。
以下是我将用更惯用的现代Python
编写的内容def reformat(fin, fout):
fout.write(next(fin)) # just copy the first line (the header) to output
for line in fin:
fields = line.split(' ')
# Make a format header specific to the number of fields
fmt = '%6.2f' + ('%10.6f' * (len(fields)-1)) + '\n'
fout.write(fmt % tuple(map(float, fields)))
basenames = os.listdir(indir) # get a list of input ASCII files to be processed
for basename in basenames:
input_filename = os.path.join(indir, basename)
output_filename = os.path.join(outdir, basename)
with open(input_filename, 'r') as fin, open(output_filename, 'w') as fout:
reformat(fin, fout)
Python的禅是“应该有一个 - 最好只有一个 - 明显的方式”。有趣的是,在过去的10多年里,你的功能是“显然”是正确的解决方案,但不再是。 :)
答案 1 :(得分:1)
fin=open(indir+filename,'r') # input file
fout=open(outdir+filename,'w') # out: processed file
#code
fin.close()
fout.close()
可以写成:
with open(indir+filename,'r') as fin, open(outdir+filename,'w') as fout:
#code
在python 2.6中,您可以使用:
with open(indir+filename,'r') as fin:
with open(outdir+filename,'w') as fout:
#code
行
lines = iter(fileinput.input([indir+filename]))
没用。你可以迭代一个打开的文件(在你的情况下是fin)
您也可以line.split(' ')
代替string.split(line, ' ')
如果更改了这些内容,则无需导入字符串和文件输入。
编辑:我不知道你可以使用内联代码。那太酷了
答案 2 :(得分:0)
在我的构建脚本中,我有以下代码:
inFile = open(sourceFile,'r')
outFile = open(targetFile,'w')
for line in inFile:
line = doKeywordSubstitution(line)
outFile.write(line)
inFile.close()
outFile.close()
我不知道如何使这更简洁。将换行逻辑放在不同的功能中看起来更适合我。
我可能会忽略您的代码,但我不明白为什么您有lines = iter(fileinput.input([indir+filename]))
。
答案 3 :(得分:0)
我不明白你为什么使用:string.split(line, ' ')
而不只是line.split(' ')
。
好吧,也许我会写这样的字符串处理部分:
values = line.split(' ')
values[0] = '{0:6.2f}'.format(float(values[0]))
values[1:] = ['{0:10.6f}'.format(float(v)) for v in values[1:]]
fout.write(' '.join(values))
至少对我来说这看起来更好但这可能是主观的:)
而不是indir
我会使用os.curdir
。而不是"./processed"
我会这样做:os.path.join(os.curdir, 'processed')
。