2017-06-01 35 views
0

我試圖運行此代碼並遇到運行時錯誤。我無法調試代碼。我確信錯誤在於函數huffman_encode和huffman_decode。顯示的錯誤是資源警告錯誤。下面是代碼: -Python中運行時/資源警告錯誤

from linked_list import * 
from huffman_bits_io import HuffmanBitsWriter as writer, HuffmanBitsReader as reader 
import unittest 

class Leaf: 
    '''class that implements Leaf''' 
    def __init__(self, parent, value, code, frequency): 
     self.parent = parent 
     self.frequency = frequency 
     self.value = value 
     self.code = code 
    def __eq__(self, other): 
     return type(other) == Leaf and self.parent == other.parent and self.frequency ==other.frequency and self.value==other.value and self.code==other.code 
    def __repr__(self): 
     return "[ {}, frequency = {} ]".format(self.code, self.frequency) 


class Node: 
    '''class that implements Node''' 

    def __init__(self, parent, code, lchild, rchild, frequency): 
     self.parent = parent 
     self.code = code 
     self.frequency = frequency 
     self.lchild = lchild 
     self.rchild = rchild 
    def __eq__(self, other): 
     return type(other) == Node and self.parent==other.parent and self.code == other.code and self.frequency == other.frequency and self.lchild == other.lchild and self.rchild == other.rchild 
    def __repr__(self): 
     return "{}, freq = {}\n\left = {}\n\right = {}".format(self.code, self.frequency, self.lchild.___repr__(), self.rchild.__repr__()) 


def strip(string, seq): 
    '''this function cuts sequence from beginning of string if possible and returns result ''' 
    if len(seq) > len(string): 
     return string 
    for i in range(len(seq)): 
     if seq[i] != string[i]: 
      return string 
    else: 
     return string[len(seq):] 


def find(lst, item): 
    '''this function finds index of first occurrence of given element in the list and returns it or raise error if there is no such element''' 
    for i in range(lst.length): 
     if get(lst, i).value[0] == item: 
      return i 
    else: 
     raise ValueError 


def string_traverse(node): 
    '''this function returns string representation of tree in pre-order traversal''' 
    lst = empty_list() 
    traverse(node, lst) #calls traverse 
    result_string = '' 
    for i in range(lst.length): #accumulate string from lst list 
     result_string += chr(get(lst, i).value) 
    return result_string 


def traverse(node, code): 
    '''this function traverse the try and return list of leaf's value(helper for string_traverse)''' 
    if type(node) == Leaf: 
     code = add(code, node.value, code.length) #if node is Leaf than terminate recursion and return character 
    else: 
     traverse(node.lchild, code) #recursive call 
     traverse(node.rchild, code) #recursive call 


def count_occurrences(file_name): 
    '''this function returns list that represent occurrence of every character of given string''' 
    with open(file_name) as file: #reads file 
     data = file.read() 
    lst = list() 
    for i in range(len(data)): #creates list of integer representation of string 
     lst.append(ord(data[i])) 
    data = lst 
    lst = empty_list() 
    for char in data: #this loop calculates occurrences of characters in the string 
     try: 
      index = find(lst, char) 
      lst = set(lst, index, (char, get(lst, index).value[1] + 1)) 
     except ValueError: 
      lst = add(lst, (char, 1), 0) 
    lst = sort(lst, lambda x: x.value[1], False) #sorts occurrences 
    return lst 


def comes_before(el1, el2): 
    '''this function returns True if el1 leaf should come before el2 leaf in Huffman tree meaning''' 
    if el1[1] < el2[1] or (el1[1] == el2[1] and type(el1[0]) is int and type(el2[0]) is int and el1[0] < el2[0]): 
     return True 
    else: 
     return False 


def build_tree(occurrences): 
    '''this function returns Huffman tree based on given list of occurrences''' 
    if occurrences.length == 1: #if we have only one character returns Leaf with this character and code '0' 
     return Leaf(None, get(occurrences, 0).value[0], '0', get(occurrences, 0).value[1]) 
    while occurrences.length != 1: #algorith described in the task 
     el1, occurrences = remove(occurrences, 0) 
     el2, occurrences = remove(occurrences, 0) 
     el1, el2 = el1.value, el2.value 
     if not comes_before(el1, el2): #finds order of elements in the tree 
      el1, el2 = el2, el1 
     new = Node(None, '', None, None, el1[1] + el2[1]) #creates new node 
     if type(el1[0]) is Node: 
      el1[0].code = '0' #sets up code for node 
      el1[0].parent = new 
      new.lchild = el1[0] 
     else: 
      new.lchild = Leaf(new, el1[0], '0', el1[1]) #if el1 is character not Node we will create leaf for that character 
     if type(el2[0]) is Node: 
      el2[0].code = '1' #sets up code for node 
      el2[0].parent = new 
      new.rchild = el2[0] 
     else: 
      new.rchild = Leaf(new, el2[0], '1', el2[1]) #if el2 is character not Node we will create leaf for that character 
     occurrences = insert_sorted(occurrences, (new, new.frequency), comes_before) #inserts new node 
    return get(occurrences, 0).value[0] 


def collect_code(node, code = ''): 
    '''this function traverse Huffman tree and collect code for each leaf and returns them as nested list(helper for create_code)''' 
    if type(node) == Leaf: 
     lst = empty_list() 
     return add(lst, (node.value, code + node.code), 0) #if node is Leaf terminates recursion and returns code for the leaf 
    else: 
     lst = empty_list() 
     lst = add(lst, collect_code(node.lchild, code + node.code), 0) #recursive call 
     lst = add(lst, collect_code(node.rchild, code + node.code), 0) #recursive call 
     return lst 


def create_code(tree): 
    '''this function unpack result of calling collect_code and return Huffman code as a list of tuples''' 
    code = collect_code(tree) #calls collect code 
    i = 0 
    while i < code.length: #this loop unpacks list 
     if type(get(code, i).value) is not tuple: 
      item, code = remove(code, i) 
      for j in range(item.value.length): 
       code = add(code, get(item.value, j).value, i) 
      continue 
     i += 1 
    return code 


def huffman_encode(input_file, output_file): 
    '''task describe this function''' 
    occurrences = count_occurrences(input_file) 
    tree = build_tree(occurrences) 
    string = empty_list() 
    t = traverse(tree, string) 
    code = create_code(tree) 
    with open(input_file) as file: 
     string = file.read() 
    result_string = '' 
    for i in range(len(string)): #this loop encodes string using code produced by create_code function 
     for j in range(code.length): 
      temp = get(code, j).value 
      if string[i] == chr(temp[0]): 
       result_string += temp[1] 
       break 
    for i in range(occurrences.length): 
     temp = get(occurrences, i).value 
     occurrences = set(occurrences, i, (chr(temp[0]), temp[1])) 
    occurrences = sort(occurrences, lambda x: x.value[0], False) 
    file = writer(output_file) 
    file.write_int(code.length) 
    for i in range(occurrences.length): 
     temp = get(occurrences, i).value 
     file.write_byte(ord(temp[0])) 
     file.write_int(temp[1]) 
    file.write_code(result_string) 
    file.close() 
    return string_traverse(tree) 


def huffman_decode(input_file, output_file): 
    '''task describe this function''' 
    file = reader(input_file) 
    number_of_codes = file.read_int() 
    occurrences = empty_list() 
    for i in range(number_of_codes): 
     char = file.read_byte() 
     number = file.read_int() 
     occurrences = add(occurrences, (char, number), 0) 
    occurrences = sort(occurrences, lambda x: x.value[1], False) 
    tree = build_tree(occurrences) 
    code = sort(create_code(tree), lambda x: x.value[0], False) 
    occurrences = sort(occurrences, lambda x: x.value[0], False) 
    quantity_of_bits = 0 
    for i in range(code.length): 
     quantity_of_bits += get(occurrences, i).value[1]*len(get(code, i).value[1]) 
    occurrences = sort(occurrences, lambda x: x.value[1], False) 
    bit_string = '' 
    for i in range(quantity_of_bits): 
     bit_string = bit_string + ('1' if file.read_bit() else '0') 
    result_string = '' 
    while bit_string: #this loop decodes string using code produced by create_code function 
     for j in range(code.length): 
      temp = get(code, j).value 
      stripped = strip(bit_string, temp[1]) 
      if len(stripped) < len(bit_string): 
       result_string += chr(temp[0]) 
       bit_string = stripped 
       break 
     with open(output_file, 'w') as file: 
      file.write(result_string) 
      file.close() 









class Test(unittest.TestCase): 


    def test_strip1(self): 
     self.assertEqual(strip('123456', '123'), '456') 

    def test_strip2(self): 
     self.assertEqual(strip('123', '4567'), '123') 

    def test_strip3(self): 
     self.assertEqual(strip('123', '456'), '123') 

    def test_find(self): 
     lst = empty_list() 
     lst = add(lst, (1, 'b'), 0) 
     lst = add(lst, (2, 'a'), 1) 
     self.assertEqual(find(lst, 2), 1) 


    def test_find_raise(self): 
     lst = empty_list() 
     lst = add(lst, (1, 'b'), 0) 
     lst = add(lst, (2, 'a'), 1) 
     self.assertRaises(ValueError, find, lst, 5) 


    def test_occurrences(self): 
     lst = empty_list() 
     lst = add(lst, (97, 5), 0) 
     lst = add(lst, (98, 3), 0) 
     lst = add(lst , (99, 7), 2) 
     self.assertEqual(str(count_occurrences(r'test2.txt')), str(lst)) 


    def test_create_code_and_tree_build(self): 
     occurrences = count_occurrences(r'test2.txt') 
     tree = build_tree(occurrences) 
     code = create_code(tree) 
     code = sort(code, lambda x: x.value[0], False) 
     self.assertEqual(str(code), "[(97, '11'), (98, '10'), (99, '0')]") 


    def test_huffman_encode_decode(self): 
     string = huffman_encode(r'test1.txt', r'test_out.txt') 
     huffman_decode(r'test_out.txt', r'test_decode.txt') 
     self.assertEqual(string, 'a') 
     with open(r'test1.txt') as file1: 
      with open(r'test_decode.txt') as file2: 
       self.assertEqual(file1.read(), file2.read()) 
       file2.close() 
      file1.close() 

    def test_huffman_encode_decode3(self): 
     string = huffman_encode(r'test2.txt', r'test2_out.txt') 
     huffman_decode(r'test2_out.txt', r'test2_decode.txt') 
     self.assertEqual(string, 'cba') 
     with open(r'test2.txt') as file1: 
      with open(r'test2_decode.txt') as file2: 
       self.assertEqual(file1.read(), file2.read()) 
       file2.close() 
      file1.close() 


    def test_huffman_encode_decode2(self): 
     string = huffman_encode(r'test3.txt', r'test3_out.txt') 
     huffman_decode(r'test3_out.txt', r'test3_decode.txt') 
     self.assertEqual(string, 'edcba') 
     with open(r'test3.txt') as file1: 
      with open(r'test3_decode.txt') as file2: 
       self.assertEqual(file1.read(), file2.read()) 
       file2.close() 
      file1.close() 




if __name__ == '__main__': 
    unittest.main() 

而以下是錯誤: -

... 
Warning (from warnings module): 
    File "C:\Users\Vikas\Documents\fwdregardingprojectdevelopment\huffman.py", line 212 
    with open(output_file, 'w') as file: 
ResourceWarning: unclosed file <_io.BufferedReader name='test_out.txt'> 
. 
Warning (from warnings module): 
    File "C:\Users\Vikas\Documents\fwdregardingprojectdevelopment\huffman.py", line 212 
    with open(output_file, 'w') as file: 
ResourceWarning: unclosed file <_io.BufferedReader name='test3_out.txt'> 
. 
Warning (from warnings module): 
    File "C:\Users\Vikas\Documents\fwdregardingprojectdevelopment\huffman.py", line 212 
    with open(output_file, 'w') as file: 
ResourceWarning: unclosed file <_io.BufferedReader name='test2_out.txt'> 
..... 
---------------------------------------------------------------------- 
Ran 10 tests in 0.272s 

OK 

請幫我在爲它是一個一天解決這個錯誤。

在此先感謝

+0

我不是100%肯定,但是我認爲問題在於,在這一行上,您將'file'(之前保存了輸入文件)分配給新的東西,而不是先關閉它。也許在'while'循環之前修改'file.close()'? (我只是假設'file'擁有一個類似文件的對象。) – smarx

+0

完美@smarx ...非常感謝。我按照你所說的做了,並在while循環之前放了file.close(),並且它沒有任何錯誤地運行。非常感謝.. :) –

回答

0

似乎在「out_file」被打開,沒有關閉 找到它被打開並關閉你的代碼文件的地方:

out_file.close() 
+0

我沒有在代碼中看到任何提及的'out_file'。我錯過了什麼? – smarx

+0

[https://stackoverflow.com/questions/21057942/python-unclosed-resource-is-it-safe-to-delete-the-file] –