我正在尝试编写一个程序,该程序接受一个包含数字列表的文件,并使用这些数字中的每一个来对字符串的一部分进行子集化。当我尝试调用我的函数时(下面)我收到错误:
TypeError: unsupported operand type(s) for -: 'str' and 'int'
我尝试将for循环中的i
更改为int(i)
,以防由于某种原因,i
不是整数但导致以下错误:< / p>
ValueError: invalid literal for int() with base 10: ''
代码:
#Function Collects Sequences and Writes to a Files
def gen_insertion_seq(index, seq, gene):
output = open("%s_insertion_seq.txt" % gene, 'w')
indices = index.read()
sequence = seq.read()
for i in indices:
site = sequence[i-9:i+15]
output.write(site + '\n')
#Open Index Files
shaker_index = open("212_index.txt")
kir2_index = open("214_index.txt")
asic1a_index = open("216_index.txt")
nachra7_index = open("252_index.txt")
#Open Sequence Files
shaker_seq = open("212_seq.txt")
kir2_seq = open("214_seq.txt")
asic1a_seq = open("216_seq.txt")
nachra7_seq = open("252_seq.txt")
#Call function on Index and Sequence Files - Should output list of generated Sequences for insertion sites.
#Must hand check first couple
gen_insertion_seq(shaker_index, shaker_seq, 'shaker')
示例输入文件:
212_index.txt
1312
210
633
696
1475
637
1198
645
1504
361
651
...
212_seq.txt
ATGGCCGCCGTGGCACTGCGAGAACAACAGCTCCAACGAAATAGTCTGGATGGATACGGTTCACTGCCTAAACTGTCTAGCCAAGACGAAGAAGGTGGCGCCGGCCATGGCTTCGGTGGGGGC
答案 0 :(得分:0)
代码中的错误是由于read
没有达到您预期的效果所致。 Called without parameters,它将整个文件读入一个字符串。然后迭代字符串中的字符而不是文件中的数字。当您在序列的索引中执行'1' - 9
时,会发生TypeError
。
您将迭代值转换为int
的直觉基本上是正确的。但是,由于您仍然在迭代字符,因此您会获得int('1')
,int('3')
,int('1')
,int('2')
,然后是来自int('\n')
的{{3}} 。 read
按原样读取整个文件,新行和所有文件。
幸运的是,文件中的行ValueError
为file object。这意味着您可以执行for line in file: ...
之类的操作,line
将采用您要解析的每个索引的字符串值。它还有额外的好处,就是可以从行中删除行结尾,这意味着您可以将其直接传递到int
而不需要进一步修改。例如。
您可以对代码进行许多其他改进,包括使其正常工作的更正。
根据@ Acccumulation的建议,在iterable块中打开文件,以确保在程序崩溃时正确清理它们,例如来自I / O错误。当块结束时它也会自动关闭文件,这是你目前根本没有做的事情(但应该是)
从概念上讲,根本不需要传递文件对象。您只能在一个地方使用每一个用于一个目的。我甚至会扩展这一点,建议您编写一个小函数来将每种文件类型解析为可用格式,然后传递它。
文件可在Python中按行迭代。这对于索引文件尤其方便,索引文件是一种非常面向行的格式。您根本不需要完整read
,并且可以从@MaximTitarenko的评论中节省几个步骤。
您可以直接在文件上使用with
来合并任何包含换行符的序列。
结合所有建议,您可以执行以下操作:
def read_indices(fname):
with open(fname, 'r') as file:
return [int(index) for index in file]
def read_sequence(fname):
with open(fname, 'r') as file:
return ''.join(file)
由于文件是字符串的可迭代,您可以在str.join
中使用它们,也可以使用字符串连接操作。您的其余代码现在看起来会更清晰:
def gen_insertion_seq(index, seq, gene): indices = read_indices(index) sequence = read_sequence(seq) with open("%s_insertion_seq.txt" % gene, 'w') as output: for i in indices: site = sequence[i-9:i+15] output.write(site + '\n') gen_insertion_seq('212_index.txt', '212_seq.txt', 'shaker') gen_insertion_seq('214_index.txt', '214_seq.txt', 'kir2') gen_insertion_seq('216_index.txt', '216_seq.txt', 'asic1a') gen_insertion_seq('252_index.txt', '252_seq.txt', 'nachra7')
您的主要功能现在更容易理解,因为它只关注序列而不关注I / O和解析等内容。你也没有一堆打开的文件句柄,等待错误。事实上,文件操作都是自包含的,远离真正的任务。
如果您有文件ID和基因名称的序列(list comprehensions),您可以通过循环进一步简化对函数的调用:
for id, gene in zip((212, 214, 216, 252), ('shaker', 'kir2', 'asic1a', 'nachra7')):
gen_insertion_seq('%d_index.txt' % id, '%d_seq.txt' % id, gene)
PS。 Python教程中的in the Python sense部分非常好。关于I/O的部分可能是您特别感兴趣的。
答案 1 :(得分:-3)
尝试使用双引号'shaker'
输入"shaker"
。或者,在你的函数中使用str(gene)。
好的,我刚刚意识到它是python所以引用的东西不应该重要,我想
或open("{}_insertion_seq.txt".format(gene), 'w')
如果是在写,请更改output.write(site + '\n')
到output.write(str(site) + '\n')