this code has this error and I am absolutely lost how to fix it. the code runs fine until it gets to the last object saved in the database and after that it throws this error. the code is a tool that checks the html of a website between 2 points in time to check if it has an error, even if the website is running well and giving a 200 response code
This is the error:
in check_html print(monitor.url) AttributeError: 'QuerySet' object has no attribute 'url'
def run_monitors():
delete_from_db()
monitors = Monitor.objects.filter(is_active=True)
monitors._fetch_all()
asyncio.run(_run_monitors(monitors))
check_html(monitor=monitors)
def check_html(monitor):
start_time = time.time()
print(monitor.url)
# The URLs to compare
old_html = monitor.html_compare
new_url = monitor.url
# Get the HTML of each URL
try:
old_html = old_html
# html1.raise_for_status()
except Exception as e:
print(e)
try:
html2 = requests.get(new_url)
html2.raise_for_status()
except Exception as e:
print(e)
return None
html2 = html2.text[:10000]
# Create a SequenceMatcher object to compare the HTML of the two URLs
matcher = difflib.SequenceMatcher(None, old_html, html2)
similarity_ratio = matcher.ratio() * 100
response_time = time.time() - start_time
monitor.html_compare = html2
html_failure = False
counter = monitor.fault_counter
if similarity_ratio <= 90 and counter == 0:
print(f"The two HTMLs have {similarity_ratio:}% in common.")
print("change detected")
html_failure = False
counter += 1
elif similarity_ratio > 90 and counter == 0:
print(f"The two HTMLs have {similarity_ratio:.2f}% in common.")
print("no change detected")
html_failure = False
counter = 0
elif similarity_ratio > 90 and counter >= 1:
print(f"The two HTMLs have {similarity_ratio:.2f}% in common.")
if counter >= 4:
print(f"HTML fault detected")
html_failure = True
else:
counter += 1
print(f"checks if fault persists, current fault counter: {counter}")
elif similarity_ratio < 90 and counter >= 1:
print("Fault is presumably resolved")
html_failure = False
counter = 0
monitor.fault_counter = counter
# Print the similarity ratio between the two URLs
monitor.save(update_fields=['html_compare', 'fault_counter'])
return html_failure
def send_notifications():
for monitor in Monitor.objects.all():
multiple_failures, last_result = has_multiple_failures(monitor)
result = check_html(monitor)
no_notification_timeout = (not monitor.last_notified) or \
monitor.last_notified < timezone.now() - timedelta(hours=1)
if multiple_failures and no_notification_timeout and monitor.is_active:
_send_notification(monitor, last_result)
if result:
_send_notification(monitor, last_result)
I already tried to put a for loop around the 'check_html' function that iterates over every object in monitor but that just returns that monitors can't be iterated over. it was a long shot but still didn't work
You have passed the queryset to the check_html() function. Using a filter we get one or more items that are iterable. You can use the for loop in check_html() function or password only one object to the function.
I found the issue. I had added the check_html function to run on a certain command. Which at the end of the script tried to give the whole queryset to the check_html function itself.
So I just had to remove the check_html function from run_monitor.
Thank you for your help guys.
Related
I created a program that I'm distributing. The program checks for username availability, and after each check a variable named checkedCount gets updated. Each check costs about 4mb or ram, which makes the total memory usage high. For example, I ran the program for about two hours which resulted in 7gb's of ram being in use. I've tried to use clear = lambda: os.system('cls') after each request to clear the terminal, but that didn't work.
Code:
def screen(self):
clear()
print(r"""
/~\
C oo
_( ^)
/ ~\
""")
print(f"""{Fore.LIGHTBLACK_EX}[>]{Fore.RESET} Checks: {self.checkedCount}
{Fore.LIGHTBLACK_EX}[>]{Fore.RESET} Claims: {self.claimedCount}
{Fore.LIGHTBLACK_EX}[>]{Fore.RESET} Errors: {self.errorCount}
""")
def checker(self):
self.proxer = self.proxies()
while True:
self.screen()
[self.usernames.put(line.strip()) for line in open(f"external/{wordlistInput}")]
name = self.usernames.get(); self.usernames.put(name)
url = f"https://public-ubiservices.ubi.com/v3/profiles?nameOnPlatform={name}&platformType=uplay"
if len(name) > 2:
try:
r = requests.get(url, headers=self.headers, proxies=self.proxer)
ctypes.windll.kernel32.SetConsoleTitleW(f"{datetime.now().strftime('%H:%M')} | Developed by gxzs#2979")
if self.checkedCount % 75 == 0:
self.checkedCount += 1
self.proxer = self.proxies()
self.login()
if r.status_code == 200:
self.checkedCount += 1
if len(r.json()['profiles']) != 0:
pass
else:
self.create(name)
else:
with open('external/errors.txt', "a") as errorFile:
errorFile.write(f"{datetime.now().strftime('%H:%M')} | Error message: {r.text}\n")
self.errorCount += 1
self.proxer = self.proxies()
self.login()
except Exception:
pass
Edit: It doesn't seem to be a issue with the variable checkedCount. I removed it from the code and it still happens
I do not know what kind of data struture is self.username and if the .put() method overwrites already existing entries, but if it doesn't then
the line:
[self.usernames.put(line.strip()) for line in open(f"external/{wordlistInput}")]
Will put the content of f"external/{wordlistInput}" at every iteration in your while True: inside self.usernames without ever clearing it's content.
Also you are not exiting the while, I don't know if its intentional.
This is a shot in the dark since there isn't more information available.
I have 3 file. The find_threshold_l.py, simplelogicbuffer_l.py and test_find_threshold_l.py.
I need to import the first two files into the last one.
This is the class in the simplelogicbuffer_l.py file:
class SimpleLogicBuffer:
def __init__(self, on_threshold):
self.on_threshold = on_threshold
self.output_state = False
def apply_input_voltage(self, value):
self.output_state = value > self.on_threshold
def is_on(self):
return self.output_state
Here's the code in the find_threshold_l.py file:
from simplelogicbuffer_l import SimpleLogicBuffer
def find_threshold(input_value, output_state):
if output_state == True:
while output_state == True:
input_value -= 10
if input_value > SimpleLogicBuffer.DUT_Logic_Buffer.on_threshold:
continue
else:
SimpleLogicBuffer.DUT_Logic_Buffer.output_state = False
input_value
return input_value / 1000
break
else:
while output_state == False:
input_value += 10
if input_value <= SimpleLogicBuffer.DUT_Logic_Buffer.on_threshold:
continue
else:
SimpleLogicBuffer.DUT_Logic_Buffer.output_state = True
input_value -= 10
return input_value / 1000
break
Here's what I wrote in the last file:
from simplelogicbuffer_l import SimpleLogicBuffer
from find_threshold_l import find_threshold
DUT_Logic_Buffer = SimpleLogicBuffer(12500)
print("The threshold voltage is {}V".format(find_threshold(11000, DUT_Logic_Buffer.is_on())))
But when I run this code, there's a error.
It said: AttributeError: type object 'SimpleLogicBuffer' has no attribute 'DUT_Logic_Buffer'
I'm a little confused. Is there something to do with the print function call or other reason?
Thanks.
This will throw an error because your DUT_Logic_Buffer_1 is only available to you in test_find_threshold_l, and your SimpleLogicBuffer does't have any attribute DUT_Logic_Buffer_1. You can solve this error by pass ing the value in the function find_threshold directly instead of SimpleLogicBuffer.DUT_Logic_Buffer_1.on_threshold, or you can do directly as: SimpleLogicBuffer(some_value).on_threshold
Cont = 1
while Cont == 1:
try:
while Cont == 1:
counter = counter + 0.1
counter = round(counter, 1)
print(counter)
time.sleep(0.1)
if counter == crashNumber:
Cont = 0
except KeyboardInterrupt:
Multiplier = counter
Here the counter will continue to count up unitl it reaches the crashNumber, when Ctrl + C is pressed, it will take the number that the counter is at and use it for the Multiplier to be used later.
However I only want to give the user the chance to press this once, then it is disabled. Is there any way that this can be done?
The KeyboardInterrupt exception will be thrown whether you want it or not: the solution, then, is to deal with the exception in different ways in your except block. My chosen implementation will use a simple boolean value that starts as True and is set to False on the first interruption:
import time
allow_interrupt = True
while True:
try:
time.sleep(1)
print ('...')
except KeyboardInterrupt:
if allow_interrupt:
print ('interrupted!')
allow_interrupt = False
Let me know if this addresses your use case.
Second modification to the script (changes made below)
Made the changes mentioned in the comments (renamed all to print_all, and added the excepetion, changed the code below to reflect the same)
However, execution still exits without any reason
Initial query:
The following is a script that tries to identify various anagrams of a word (as in the website: http://wordsmith.org/anagram/anagram.cgi?anagram=suchindra&t=1000&a=n):
import sys
import itertools
import threading
from collections import defaultdict
words_dict = defaultdict(lambda: "")
def lower_and_nocrlf(s):
return s.lower().strip()
def two_or_more(s):
if len(s) >= 1:
return 1
else:
return 0
def get_perms(cur_iter):
lst = []
for i in range(0, 10000):
try:
lst.append("".join(cur_iter.next()))
except:
break
return lst
def get_twordlist(z):
lst1 = []
lst2 = []
for i in range (1, len(z)):
lst1.append(z[:i])
lst2.append(z[i:])
return lst1, lst2
def filter_dict(x):
if x in words_dict.keys():
return x
else:
return 0
def main():
print_all = None
word = None
try:
word = sys.argv[1]
print_all = sys.argv[2]
except:
pass
if word == None:
try:
word = sys.stdin.readline()
print_all = sys.stdin.readline()
except:
pass
if word == None:
sys.exit(1)
fd = open('/usr/apps/words', 'r')
words = fd.readlines()
fd.close()
words_lower = map(lower_and_nocrlf, words)
words_lower = filter(two_or_more, words_lower)
from collections import defaultdict
for i in words_lower:
words_dict[i] = ""
iter = itertools.permutations(word)
all_permutations = []
iters = []
for i in range(0, 100):
iters.append(iter)
result = map(get_perms, iters)
main_list = []
for l in result:
if l != []:
for word in l:
main_list.append(word)
results = []
try:
main_list_len = len(main_list)
for index in range(0, main_list_len):
percent = (index/len(main_list)) * 100
lst1, lst2 = get_twordlist(main_list[index])
result1 = map(filter_dict, lst1)
result2 = map(filter_dict, lst2)
for index in range(0, len(result1)):
if (result1[index] != 0) and (result2[index] != 0):
results.append("%s %s" % (result1[index], result2[index]))
except KeyboardInterrupt:
print("User stopped execution, partial results:")
print results
sys.exit(1)
except Exception:
# catches all other types of exception here
print(sys.exc_info())
traceback.print_exc()
print(results)
if __name__ == "__main__":
try:
main()
except:
sys.exit(0)
So, your code is clearly executing down to the print index line and then failing somewhere inside the block. The exception handler only catches exceptions of type KeyboardInterrupt - i.e. when a user presses Ctl+C on their keyboard. Any other error will exit via the sys.exit(0) method, so you have no way of knowing what the error is.
Personally I quite like the traceback module for these printing out errors, so I suggest you modify your try catch block to be something like:
import traceback
try:
main_list_len = len(main_list)
print main_list_len
for index in range(0, main_list_len):
print index
percent = (index/len(main_list)) * 100
lst1, lst2 = get_twordlist(main_list[index])
result = map(filter_dict, lst1, lst2)
results.append[result]
except KeyboardInterrupt:
print("User stopped execution, partial results:")
print("Exception: %s" % (sys.exc_info()))
print results
except Exception:
# catches all other types of exception here
traceback.print_exc()
This will allow you to debug the problem as the traceback module will give you line numbers and an error message to work with.
Good luck!
OK after some analysis, it looks like filter does not accept more than one list. The second issue is because I am using multiple lists in the filter
I'm going to create statistics based on information what builds were success or not and how much per project.
I create ProjectStat class per new project I see and inside handled statistics. For printing overall statistic I need to pass through all ProjectStat instances. For printing success statistics per project I need to pass through them again and so on, on any kind of statistics. My question is about simplifying the way handling the cycles, i.e not to pass the dictionary every time. Perhaps using decorators or decorator pattern would be pythonic way? How then they can be used if number of instances of ProjectStat is dynamically changed?
Here is the code:
class ProjectStat(object):
projectSuccess = 0
projectFailed = 0
projectTotal = 0
def addRecord(self, record):
if len(record) == 5: record.append(None)
try:
(datetime, projectName, branchName, number, status, componentName) = record
except ValueError:
pass
self.projectTotal += 1
if status == 'true': self.projectSuccess += 1
else: self.projectFailed += 1
def addDecorator(self, decorator):
decorator = decorator
def readBuildHistoryFile():
dict = {}
f = open("filename")
print("reading the file")
try:
for line in f.readlines():
#print(line)
items = line.split()
projectName = items[1]
projectStat = dict[projectName] = dict.get(projectName, ProjectStat())
projectStat.addRecord(items)
print(items[1])
finally:
f.close()
success = 0
failed = 0
total = 0
for k in dict.keys():
projectStat = dict[k]
success += projectStat.projectSuccess
failed += projectStat.projectFailed
total += projectStat.projectTotal
print("Total: " + str(total))
print("Success: " + str(success))
print("Failed: " + str(failed))
if __name__ == '__main__':
readBuildHistoryFile()
I'm not sure I understand the Q, but I'll try to answer anyway :)
option1:
total = sum([project.projectTotal for project in dict.values()])
success = sum([project.projectSuccess for project in dict.values()])
failed = sum([project.projectFailed for project in dict.values()])
option2:
(total,success,failed) = reduce (lambda x,y:(x[0]+y[0],x[1]+y[1],x[2]+y[2]), [(project.projectTotal,project.projectSuccess,project.projectFailed) for project in dict.values()])