I was working on some code which retrieves a line in a text file ("save[#]) with the format:
"[name],[boolean or integer value]"
(The aim is to be able to retrieve it for save states of a game)
The issue is that whenever I try to return a value from my module I get the following:
Traceback (most recent call last):
File "//IHS-FS-001.ihs.local/Cohort2020$/2ELGAG1/python/srctg/test.py", line 5, in <module>
retrieve()
File "//IHS-FS-001.ihs.local/Cohort2020$/2ELGAG1/python/srctg/test.py", line 3, in retrieve
if retrieve.check("test", 1) == True:
AttributeError: 'function' object has no attribute 'check'
The test attribute is a testing module set up to test the code for the game:
import retrieve.py
def retrieve():
if retrieve.check("test", 1) == True:
return True
retrieve()
The retrieve attribute itself is set up like so:
import error
def check(i_name, save):
save = str(save)
save_n = "save" + save + ".txt"
save_f = open(save_n, "r")
list = save_f.readlines()
for item in range(len(list)):
list[item] = list[item].strip()
list[item] = list[item].split(",")
list[item][1] = list[item][1]
for item in range(len(list)):
if i_name == list[item][0]:
i_return = list[item][1]
if bool_check(i_return) == True:
i_return = bool(i_return)
elif int_check(i_return) == True:
i_return = int(i_return)
else:
print(error.code("001"))
return "error"
return i_return
def int_check(value):
while True:
try:
value = int(value)
return True
break
except ValueError:
return False
break
def bool_check(value):
while True:
try:
value = bool(value)
return True
break
except ValueError:
return False
break
Don't include the .py in the import. This tries to import a module named py inside the package named retrieve, which is probably not what you meant.
import retrieve as retrieve_module
def retrieve():
if retrieve_module.check("test", 1) == True:
return True
Also, don't write a function with the same name as the module you just imported. Change the name of one or the other. That's why it can't find the .check attribute. It's looking inside the retrieve function instead of inside the retrieve module because you overwrote it in the global namespace (by executing the function definition) before you called the function.
Related
I have two different modules (files) where I store different objects.
The work flow is - call objects from different files and return the values from the database. If I call object from file_1 below, it returns required values from the database. However when I call object from file_1 in file_2, it returns 'None' even though input parameter is supplied.
file_1
class Database(object):
database = None
host = None
port = None
def __init__(self, host=None, port=None):
self.host=None
self.port=None
def client_(self):
return MongoClient()
def find_spefic_director(self, db=None, coll=None, directorId=None):
'''If when a specific director id is supplied it returns director related information'''
project={'_id': 0}
filter={'directorid': directorId}
print(directorId)
if not directorId is None:
result = self.client_()[db][coll].find(projection=project,
filter=filter)
return [i for i in result]
else:
return 'valid Id is required'
if __name__ == "__main__":
Database()
file_2
class Graph(object):
def __init__(self, host=None, port=None):
self.host=None
self.port=None
self.directorId=None
def minMaxDate(self, db=None, coll=None, directorId=None):
dr= Database(self.host, self.port).find_spefic_director(self.directorId)
drt=dr(directorId)
return drt
if __name__ == "__main__":
Graph()
Now I am trying to call Database() in file 2 for further processing in a different file
from file_1 import Database
from file_2 import Graph as gc
gc(directorId=340769.0).minMaxDate(db, coll='directory', directorId=340769.0)
when I run, it returns
None
TypeError Traceback (most recent call last)
<ipython-input-3-2d56a89c0288> in <module>
----> 1 gc().minMaxDate(db, coll='crsp_na_wrds_company_director_names', directorId=340769.0)
~/graph_construct.py in minMaxDate(self, db, coll, directorId)
25
26 dr= Database(self.host, self.port).find_spefic_director(self.directorId)
---> 27 drt=dr(directorId)
28
29
TypeError: 'str' object is not callable
What should be done to return the values stored in the database?
I am making an app which will return one random line from the .txt file. I made a class to implement this behaviour. The idea was to use one method to open file (which will remain open) and the other method which will close it after the app exits. I do not have much experience in working with files hence the following behaviour is strange to me:
In __init__ I called self.open_file() in order to just open it. And it works fine to get self.len. Now I thought that I do not need to call self.open_file() again, but when I call file.get_term()(returns random line) it raises IndexError (like the file is empty), But, if I call file.open_file() method again, everything works as expected.
In addition to this close_file() method raises AttributeError - object has no attribute 'close', so I assumed the file closes automatically somehow, even if I did not use with open.
import random
import os
class Pictionary_file:
def __init__(self, file):
self.file = file
self.open_file()
self.len = self.get_number_of_lines()
def open_file(self):
self.opened = open(self.file, "r", encoding="utf8")
def get_number_of_lines(self):
i = -1
for i, line in enumerate(self.opened):
pass
return i + 1
def get_term_index(self):
term_line = random.randint(0, self.len-1)
return term_line
def get_term(self):
term_line = self.get_term_index()
term = self.opened.read().splitlines()[term_line]
def close_file(self):
self.opened.close()
if __name__ == "__main__":
print(os.getcwd())
file = Pictionary_file("pictionary.txt")
file.open_file() #WITHOUT THIS -> IndexError
file.get_term()
file.close() #AttributeError
Where is my mistake and how can I correct it?
Here in __init__:
self.open_file()
self.len = self.get_number_of_lines()
self.get_number_of_lines() actually consumes the whole file because it iterates over it:
def get_number_of_lines(self):
i = -1
for i, line in enumerate(self.opened):
# real all lines of the file
pass
# at this point, `self.opened` is empty
return i + 1
So when get_term calls self.opened.read(), it gets an empty string, so self.opened.read().splitlines() is an empty list.
file.close() is an AttributeError, because the Pictionary_file class doesn't have the close method. It does have close_file, though.
While trying to create a minimal, reproducible example for another problem in Python 3.7.3, I ran into a NoneType Error that I wasn't expecting.
Main program:
import worker
def multiply_worker_value(arguments):
current_Worker = arguments[0]
multiplier = arguments[1]
new_worker = current_Worker.change_value(multiplier)
return new_worker
current_worker = worker.Worker()
print("Printing value:")
print(current_worker.get_value()[0])
while(current_worker.get_value()[0] < 10):
paramList = [current_worker,2]
current_worker = multiply_worker_value(paramList)
print(current_worker.get_value()[0])
Worker class:
import numpy
class Worker():
def __init__(self):
self.values = numpy.random.rand(10)
def change_value(self,multiplier):
self.values = numpy.sum(self.values*multiplier)
def get_value(self):
return self.values
When this is run, I get:
Printing value:
0.10619190084595542
Traceback (most recent call last):
File "F:\Visual Studio\repos\Projects2020\tests\concurrent_test\concurrent_test\main.py", line 14, in <module>
while(current_worker.get_value()[0] < 10):
AttributeError: 'NoneType' object has no attribute 'get_value'
Press any key to continue . . .
and I am not sure why this is happening.
Inside the while loop, your current_worker gets overwritten with None:
current_worker = multiply_worker_value(paramList)
this calls:
new_worker = current_Worker.change_value(multiplier)
Your Worker.change_value method does not have a return statement, so it implicitly returns None.
Then, in the second iteration of your loop, your code tries to call get_value on None, which fails.
So I'm testing my knowledge on webscraping by writing this little script (I know some things are redundant, it's just me playing around with things):
def programstart():
import re
from selenium import webdriver
from bs4 import BeautifulSoup
ff=webdriver.Firefox()
ff.get('https://www.ozbargain.com.au/deals')
linkpattern = r'https://www.ozbargain.com.au/node/.*'
donotpassthislink = 'https://www.ozbargain.com.au/node/415763'
#list of found lnks
titlelist = []
#loop to find links
while True:
soup = BeautifulSoup(ff.page_source)
raw_links = soup.find_all(name='a', href=re.compile(linkpattern))
for links in raw_links:
titles = ff.find_element_by_xpath("//h2[#class='title']").text
extract = links
if donotpassthislink == extract:
break
else:
pass
titlelist.append(titles)
# Load next page
if donotpassthislink == extract: # stop loop at first movie link from last time.
break
else:
ff.get(ff.find_element_by_xpath("//a[#class='pager-next active']").get_attribute('href'))
programstart()
I get this error:
Traceback (most recent call last):
File "F:/Dropbox/Funfile/ben.py", line 35, in <module>
programstart()
File "F:/Dropbox/Funfile/ben.py", line 29, in programstart
if donotpassthislink == extract: # stop loop at first movie link from last time.
UnboundLocalError: local variable 'extract' referenced before assignment
I find this weird since this loop was used in another script that works perfectly.
So I write a simplified script:
test = 'lets break this sentence up'
list = []
def func():
while True:
for i in test:
extract = i
print(extract)
if extract == 'u':
break
else:
pass
list.append(extract)
if extract == 'u':
print('done')
break
func()
And it executes without any issues.
What's going on?
I got distracted and ended up writing a test framework in python. I'm struggling with a particular problem that this throws up.
During my assertion, I want to throw an exception as a way of bubbling a problem up to the run_test() method without requiring the user to have any knowledge of the framework. The problem is that when I do that, it seems that the try/catch block is not honoured.
Here is a cut down version of my fledgling framework:
# test_framework.py
import inspect
import module_containing_tests
class AssertionException(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return self.message
def run_test(test_name, test_method):
try:
print(">", test_name)
test_method()
print("Passed")
except AssertionException as error:
print("Failed")
print(str(error))
def assert_true(conditional):
if not conditional:
raise AssertionException("Expected True. Was False")
def test(func):
func.is_test = True
return func
members = inspect.getmembers(module_containing_tests)
for member in members:
if "is_test" in dir(member[1]) and not member[0] == "module_containing_tests":
run_test(member[0], member[1])
The module containing the tests will look like this:
# module_containing_tests.py
from test_framework import *
#test
def passing_test():
assert_true(1 + 2 == 3)
#test
def failing_test():
assert_true(1 + 2 == 5)
The output has all the exception stack tracing in it and it also halts the execution
λ python test_framework.py
> failing_test
Traceback (most recent call last):
File "test_framework.py", line 29, in <module>
run_test(member[0], member[1])
File "test_framework.py", line 13, in run_test
test_method()
File "C:\Git\simpy-test\module_containing_tests.py", line 9, in failing_test
assert_true(1 + 2 == 5)
File "C:\Git\simpy-test\test_framework.py", line 20, in assert_true
raise AssertionException("Expected True. Was False")
test_framework.AssertionException: Expected True. Was False
What I want is something like this:
λ python test_framework.py
> failing_test
Expected True. Was False
Failed
> passing_test
Passed
I think the issue is partly in the circular reference between the two files that might mess up with the visibility of the methods (as somehow explained here) and partly, maybe, in the approach. If you think about how many other testing framework work, you often have 3 elements, the unit to test, the testing framework and a test runner.
So if we try to split everythig folllowing that logic you end up having:
test_framework.py
# test_framework.py
class AssertionException(Exception):
pass
def test(f):
f.is_test = True
return f
def assert_true(conditional):
if not conditional:
raise AssertionException("Expected True. Was False")
test_runner.py
# test_runner.py
import inspect
import unit_test
from test_framework import AssertionException
def run_test(test_name, test_method):
try:
print(">", test_name)
test_method()
print("Passed")
except AssertionException as error:
print("Failed with AssertionException: " + str(error))
except Exception as error:
print("Failed with Exception: " + str(error))
if __name__ == "__main__":
members = inspect.getmembers(unit_test)
for member in members:
if "is_test" in dir(member[1]):
run_test(member[0], member[1])
unit_test.py
# unit_test.py
from test_framework import *
#test
def a_passing_test():
assert_true(1 + 2 == 3)
#test
def z_failing_test():
assert_true(1 + 2 == 5)
With this setup the circular dependency is removed and all the visibility context are respected and the output/behaviour is the expected one.
I hope it helps.
Not sure this is what you want but this works.
Copied from here Hide traceback unless a debug flag is set
Output:
$ ./test_framework.py
> a_passing_test
Passed
> z_failing_test
test_framework.AssertionException: Expected True. Was False
First file:
#!/usr/bin/env python3
#test_framework.py
import inspect
import module_containing_tests
import sys
class AssertionException(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return self.message
def run_test(test_name, test_method):
try:
print(">", test_name)
test_method()
print("Passed")
except AssertionException as error:
print("Failed")
print(str(error))
def assert_true(conditional):
if not conditional:
raise AssertionException("Expected True. Was False")
def test(func):
func.is_test = True
return func
sys.tracebacklimit=0
members = inspect.getmembers(module_containing_tests)
for member in members:
if "is_test" in dir(member[1]) and not member[0] == "module_containing_tests":
run_test(member[0], member[1])
second file:
#!/usr/bin/env python3
#module_containing_tests.py
from test_framework import *
#test
def a_passing_test():
assert_true(1 + 2 == 3)
#test
def z_failing_test():
assert_true(1 + 2 == 5)