2017-08-10 43 views
1

所以,我對python很陌生,我不確定我的代碼是否最有效,但是如果有人能向我解釋爲什麼我的腳本會很感激我運行它時返回「名稱未定義」錯誤。我在一個單獨的文件中有300個基因名的列表,每行一個名稱,我想要讀取,並將每行存儲爲一個字符串變量。名稱未定義錯誤python逐行讀取文件時

在腳本中我有一個600個變量的列表。對於300個名稱中的每一個,300個標記爲name_bitscore和300標記爲name_length的變量。 我想根據條件篩選列表。我的腳本是這樣的:

#!/usr/bin/python 
with open("seqnames-test1-iso-legal-temp.txt") as f: 
    for line in f: 
     exec("b="+line+"_bitscore") 
     exec("l="+line+"_length") 
     if 0.5*b <= 2*1.05*l and 0.5*b >= 2*0.95*l: 
      print line 
ham_pb_length=2973 
ham_pb_bitscore=2165 
g2225_ph_length=3303 
cg2225_ph_bitscore=2278 

等爲長度和bitscore變量。

本質上,我在這裏要做的是讀取文件「seqnames-test1-iso-legal-temp.txt」的第1行,它是ham_pb。然後,我想用exec函數創建一個變量b = ham_pb_bitscore和l = ham_pb_length,這樣我就可以測試該基因位數值的一半值是否在其長度的兩倍範圍內,並具有5​​%的誤差範圍。然後,對每個基因,即文件「seqnames-test1-sio-legal-temp.txt」的每一行重複此操作。

當我執行該腳本,我得到錯誤信息:

Traceback (most recent call last): 
    File "duplicatebittest.py", line 4, in <module> 
    exec("b="+line+"_bitscore") 
    File "<string>", line 1, in <module> 
NameError: name 'ham_pb' is not defined 

我又簡短的腳本,以確保我使用exec功能正常,看起來像這樣:

#!/usr/pin/python 
name="string" 
string_value=4 
exec("b="+name+"_value") 
print(name) 
print(b) 

並且這返回:

string 
4 

所以,我知道我可以使用exec來包含一個字符串變量在變量聲明中,因爲b按預期返回4。所以,我不確定爲什麼我在第一個腳本中出現錯誤。

我測試,以確保變線輸入

#!/usr/bin/python 
    with open("seqnames-test1-iso-legal-temp.txt") as f: 
     for line in f: 
      print type(line) 

是一個字符串,並將其返回的行

<type 'str'> 

300倍,所以我知道每個變量行是一個字符串,這就是爲什麼我不明白爲什麼我的測試腳本能夠正常工作,但這並不是。

任何幫助將超級讚賞!

+1

'line'包含行結束符。你必須使用'line.rstrip()' –

+0

因此,澄清,如果第2行被換成'for line.rstrip()in f'? – Louis

+0

沒有。看到我的答案(並接受它,如果它適用於你) –

回答

0

#!/usr/bin/env python作爲第一行。有關更多解釋,請參閱this問題。

正如Jean指出的那樣,高管不是這份工作的正確工具。你應該使用字典,因爲它們不那麼危險(搜索代碼注入)和字典更容易閱讀。這裏有一個如何使用從Python文檔拍攝字典的例子:

>>> tel = {'jack': 4098, 'sape': 4139} 
>>> tel['guido'] = 4127 
>>> tel 
{'sape': 4139, 'guido': 4127, 'jack': 4098} 
>>> tel['jack'] 
4098 
>>> del tel['sape'] 
>>> tel['irv'] = 4127 
>>> tel 
{'guido': 4127, 'irv': 4127, 'jack': 4098} 
>>> list(tel.keys()) 
['irv', 'guido', 'jack'] 
>>> sorted(tel.keys()) 
['guido', 'irv', 'jack'] 
>>> 'guido' in tel 
True 
>>> 'jack' not in tel 
False 

這裏有一個辦法,我能想到的,以實現自己的目標:

with open("seqnames-test1-iso-legal-temp.txt") as f: 
    gene_data = {'ham_pb_length':2973, 'am_pb_bitscore':2165, 
       'g2225_ph_length':3303, 'cg2225_ph_bitscore':2278} 
    '''maybe you have more of these gene data things. If so, 
    just append them to the end of the above dictionary literal''' 
    for line in f: 
     if not line.isspace(): 
      bitscore = gene_data[line.rstrip()+'_bitscore'] 
      length = gene_data[line.rstrip()+'_bitscore'] 
      if (0.95*length <= bitscore/4 <= 1.05*length): 
       print line 

我採取了一些有用的Python特性的優勢在這裏。在python3中,5/7的計算結果爲0.7142857142857143,而不是許多編程語言中的典型值爲0。如果你想在python3中進行整數除法,使用5//7。另外,在Python中,1<2<3評估爲True,並且1<3<2評估爲False,而在許多編程語言中,1<2<3評估爲True<3,其可能給出錯誤或根據編程語言評估爲True

+0

這似乎很有效,因爲它打印了4個預期的結果,但後來給我一個錯誤:'KeyError:' _bitscore'' – Louis

+0

您的文件末尾可能有一些空白。 'KeyError'意味着你嘗試了一個字典查找並且失敗了。在'bitscore = gene_data [line.rstrip()+'_bitscore']'行上,'line.rstrip()'是一些迭代中的空字符串。然後Python將其作爲'bitscore = gene_data [''+'_ bitscore']'運行,它與'bitscore = gene_data ['_ bitscore']'相同。爲了解決這個問題,把'if line.isspace():'放在for循環之後和賦值語句之前(並相應地改變縮進)。這會檢查該行不是全部空白字符。我改變了我的原始答案來演示。 – asky

+0

這工作,謝謝你的幫助! – Louis

2

line是由文本文件迭代器生成的,它爲每行讀取發出一個換行符。

所以,你的表達:

exec("b="+line+"_bitscore") 

傳遞給exec爲:

b=ham_pb 
_bitscore 

地帶的輸出,並且將工作

exec("b="+line.rstrip()+"_bitscore") 

只要你移動以下行之前循環如此變化s的宣稱:

ham_pb_length=2973 
ham_pb_bitscore=2165 
g2225_ph_length=3303 
cg2225_ph_bitscore=2278 

更好:退出使用exec和使用字典,以避免動態定義變量。

+0

我現在只是得到錯誤'NameError:name'ham_pb_bitscore'未定義'。那可能是因爲它是在代碼塊之後定義的?如果不是的話,我會嘗試用字典重寫它,因爲我在其他地方讀過,以這種方式使用exec並不是最佳做法。 – Louis

+0

是的,移動上面的塊。但是,使用exec並不是最佳實踐。而且這是相當不安全的(如果你不控制文件中的內容,那可能導致代碼注入) –