Python Class with Self - Positional argument errors while calling the class - python

I am having issues with self, I have written a class to make a data comparison of two datasets which I am feeding in as a csv - while trying to call this function, I am getting a TypeError.
Here is my class
import csv
import time
import pandas as pd
start_time = time.time()
class compare_files:
def __init__(self, source, target):
self.source = source
self.target = target
def compare_csv(self):
source_file = open(self.source, "r", encoding="utf8")
target_file = open(self.target, "r", encoding="utf8")
csv_reader_source = csv.reader(source_file, delimiter=',')
csv_reader_target = list(csv.reader(target_file, delimiter=','))
columns = []
all_mistakes = []
target_line = 0
for row_source in csv_reader_source:
if target_line == 0:
for i in row_source:
columns.append(i)
target_line = 1
continue
row_target = csv_reader_target[target_line]
target_line += 1
mistakes = []
if len(row_target) != len(row_target):
if len(mistakes) == 0:
mistakes.append(row_source[0])
mistakes.append('number of columns in this row mismatch')
for i in range(len(row_source)):
if row_source[i] != row_target[i]:
if len(mistakes) == 0:
mistakes.append(row_source[0])
mistakes.append(columns[i])
mistakes.append(row_source[i])
mistakes.append(row_target[i])
if len(mistakes) > 0:
all_mistakes.append(mistakes)
return all_mistakes, round(time.time() - start_time, 2)
all_mistakes, time_taken = compare_files.compare_csv(
"source.csv", "target.csv")
for i in all_mistakes:
print(i)
print("Execution time took %s seconds" % (time_taken))
and here is the error, My compare function should accept source and target both, but when I calling compare function it seems it only accepts one argument.
~/Desktop » python3 compar2.py
Traceback (most recent call last):
File "compar2.py", line 70, in <module>
all_mistakes, time_taken = compare_files.compare_csv(
TypeError: compare_csv() takes 1 positional argument but 2 were given

you defined the two parameters in the constructor so you have to call the constructor first like this
com_files = compare_files("source.csv", "target.csv")
then call the compare_csv method without the two parameters like this
all_mistakes, time_taken = com_files.compare_csv()

Related

Calling a class method from a different file using Schedule Module in Python

I'm trying to call a method from a class that is in a different file. This is how my code looks:
main.py
###Imports
import funct as f
import schedule
import time
###More Imports
###Grabbing GPS data from user and assigning values
bboxsize = f.find(userLat, userLng, userRad)
if __name__ == '__main__':
r = f.find.radar(bboxsize) ### <---- Line 14
schedule.every(5).seconds.do(r)
while True:
schedule.run_pending()
time.sleep(1)
funct.py
###Imports
class find:
def __init__(self, userLat, userLng, userRad):
self.userLat = userLat
self.userLng = userLng
self.userRad = userRad
def bboxFormula(self):
### Lots of code that is not important to this
return bboxsize
def radar(self, bboxsize):
api = OpenSkyApi(username='###', password='###')
states = api.get_states(bbox=bboxsize)
print(f"vvvvvv| {time.ctime(time.time())} |vvvvvv")
print("------------------------------------------")
for s in states.states:
print("Callsign: %r, Latitude: %r, Longitude: %r, Altitude (meters): %r, Velocity %r)" % (s.callsign, s.latitude, s.longitude, s.geo_altitude, s.velocity))
print("------------------------------------------")
When running this I get:
Traceback (most recent call last):
File "/##/##/##/##/main.py", line 14, in <module>
r = f.find.radar(bboxsize)
TypeError: find.radar() missing 1 required positional argument: 'bboxsize'
I can run all of this in one file without classes, so I know it works. I have been messing with this for a while getting all sorts of errors with every change I make.
Is there something that I'm missing or is there no way for me to do this with the Schedule Module?
I’m just guessing here, but I think you had different code when it was all one file.
Now with two files I think you meant to write this:
find = f.find(userLat, userLng, userRad)
boxsize = find.bboxFormula()
if __name__ == '__main__':
r = lambda :find.radar(bboxsize) ### <---- Line 14
schedule.every(5).seconds.do(r)
while True:
schedule.run_pending()
time.sleep(1)

TypeError: __init__() got an unexpected keyword argument 'dir'

I try to start a timer to do some file arvchival job. the code is like this:
from threading import Timer
message_archive_dir = "achivedir"
message_archive_format = "zip"
archive_timer = Timer(86400, messageachiver.archive, dir = message_archive_dir, fmt = message_archive_format)
archive_timer.start()
class messageachiver(object):
def __init__(self, **kwargs):
self.message_archive_dir = dir
self.message_archive_format = fmt
def archive(self):
print("message_archive_dir is " + self.message_archive_dir)
print("message_archive_format is " + self.message_archive_format)
print("Archiving trade messages")
I got below error:
Traceback (most recent call last):
File "sa_listener.py", line 43, in <module>
archive_timer = Timer(archive_interval, messageachiver.archive, dir = message_archive_dir, fmt = message_archive_format)
TypeError: __init__() got an unexpected keyword argument 'dir'
I'm not sure why _init_ does not accept **kwargs.
This specific init error is because you are passing multiple variables to the timer class.
In this line:
Timer(86400, messageachiver.archive, dir = message_archive_dir, fmt = message_archive_format)
You are passing the archive function, the dir variable, and the fmt variable to TIMER and not to the messageachiver class. Timer has no named variables for dir and fmt.
So the line should be Timer(86400, messageachiver.archive)
This only partially fixes your problem though. Because you are never actually initializing the class with the variables you need them to have. So before you call timer, you need to initialize the class messageachiver by adding mymessageachiver = messageachiver(dir = message_archive_dir, fmt = message_archive_format)
Also you need to put your class definition before you try to initialize it.
The final code:
from threading import Timer
class messageachiver(object):
def __init__(self, **kwargs):
self.message_archive_dir = kwargs['dir']
self.message_archive_format = kwargs['fmt']
def archive(self):
print("message_archive_dir is " + self.message_archive_dir)
print("message_archive_format is " + self.message_archive_format)
print("Archiving trade messages")
message_archive_dir = "achivedir"
message_archive_format = "zip"
mymessageachiver = messageachiver(dir = message_archive_dir, fmt = message_archive_format)
# That's a huge wait time, try something like 10 for a smaller wait during testing.
archive_timer = Timer(86400, mymessageachiver.archive)
archive_timer.start()

How to resolve AttributeError when trying to set None as default method argument

I know there are loads of answers to this question but I'm still not getting it...
Following is sa_reporting.py
class saReport():
def __init__(self, body, to_table, normalise=False, date_col=None):
global directory
self.body = body
self.to_table = to_table
self.normalise = normalise
self.date_col = date_col if date_col is not None else []
directory = os.path.join('/Users','python', self.to_table)
if not os.path.exists(directory):
os.mkdir(directory)
def download_files(self, ...):
...
def download_reports(self, ...):
...
def get_files(self):
...
def read_file(self, file):
....
def load_to_db(self, sort_by=None): # THIS IS WHAT I THINK IS CAUSING THE ERROR
sort_by = sort_by if sort_by is not None else [] # THIS IS WHAT I TRIED TO FIX IT
def normalise_data(self, data):
dim_data = []
for row in data:
if row not in dim_data:
dim_data.append(row)
return dim_data
def convert_dates(self, data):
if self.date_col:
for row in data:
for index in self.date_col:
if len(row[index]) > 10:
row[index] = row[index][:-5].replace('T',' ')
row[index] = datetime.datetime.strptime(row[index], "%Y-%m-%d %H:%M:%S")
else:
row[index] = datetime.datetime.strptime(row[index], "%Y-%m-%d").date()
return data
print(f'\nWriting data to {self.to_table} table...', end='')
files = self.get_files()
for file in files:
print('Processing ' + file.split("sa360/",1)[1] + '...', end='')
csv_file = self.read_file(file)
csv_headers = ', '.join(csv_file[0])
csv_data = csv_file[1:]
if self.normalise:
csv_data = self.normalise_data(csv_data)
csv_data = self.convert_dates(csv_data)
if sort_by:
csv_data = sorted(csv_data, key=itemgetter(sort_by))
#...some other code that inserts into a database...
Executing the following script (sa_main.py):
import sa_reporting
from sa_body import *
dim_campaign_test = sa_reporting.saReport(
body=dim_campaign_body,
to_table='dimsa360CampaignTest',
normalise=True,
date_col=[4,5]
)
dim_campaign_test_download = dim_campaign_test.download_reports()
dim_campaign_test_download.load_to_db(sort_by=0) # THIS IS WHERE THE ERROR OCCURS
Output and error message:
Downloading reports...
The report is still generating...restarting
The report is ready
Processing...
Downloading fragment 0 for report AAAnOdc9I_GnxAB0
Files successfully downloaded
Traceback (most recent call last):
File "sa_main.py", line 43, in <module>
dim_campaign_test_download.load_to_db(sort_by=0)
AttributeError: 'NoneType' object has no attribute 'load_to_db'
Why am I getting this error? And how can I fix it?
I just want to make None be the default argument and if a user specifies the sort_by parameter then None will be replaced with whatever the user specifies (which should be an integer index)
This code would seem to suggest that dim_campaign_test_download is being set to None. As in the below line, you set it to the result of dim_campaign_test.download_reports(), it is likely that no reports are being found.
dim_campaign_test_download = dim_campaign_test.download_reports()
You might want to instead do the following, as dim_campaign_test is the saReport Object on which you probably want to operate:
dim_campaign_test.load_to_db(sort_by=0)

Python JSON Serialize Dictionary<String,Object>

I have a Dictionary with Key String (2019-10-28 13:21) and Value of Object (DataPoint)
import requests
import json
import time
symbol = "AAPL"
intraday_url = "https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol="+symbol+"&interval=1min&outputsize=full&apikey="+api_key
sma_url = "https://www.alphavantage.co/query?function=SMA&symbol="+symbol+"&interval=1min&time_period=180&series_type=open&apikey="+api_key
ema_url = "https://www.alphavantage.co/query?function=EMA&symbol="+symbol+"&interval=1min&time_period=15&series_type=open&apikey="+api_key
vwap_url = "https://www.alphavantage.co/query?function=VWAP&symbol="+symbol+"&interval=1min&apikey="+api_key
macd_url = "https://www.alphavantage.co/query?function=MACD&symbol="+symbol+"&interval=1min&series_type=open&apikey="+api_key
rsi_url = "https://www.alphavantage.co/query?function=RSI&symbol="+symbol+"&interval=1min&time_period=100&series_type=open&apikey="+api_key
adx_url = "https://www.alphavantage.co/query?function=ADX&symbol="+symbol+"&interval=1min&time_period=100&apikey="+api_key
class DataPoint:
def __init__(self, time):
# 2019-10-31 15:49:00 (original)
# 2019-10-31 15:49 (formatted)
formatted_time = time[0:len(time)-3]
self.time = formatted_time
self.open = None
self.high = None
self.low = None
self.close = None
self.volume = None
self.sma = None
self.ema = None
self.vwap = None
self.macd = None
self.rsi = None
self.adx = None
def addIntraday(self,open,high,low,close,volume):
self.open = open
self.high = high
self.low = low
self.close = close
self.volume = volume
def addTechnical(self,technical,value):
if technical == "SMA":
self.sma = value
elif technical == "EMA":
self.ema = value
elif technical == "VWAP":
self.vwap = value
elif technical == "MACD":
self.macd = value
elif technical == "RSI":
self.rsi = value
elif technical == "ADX":
self.adx = value
def getIntraday(dictionary):
url = intraday_url
response = requests.get(url)
json = response.json()
intraday = json.get("Time Series (1min)")
keys = intraday.keys()
for key in keys:
ts = intraday.get(key)
dp = DataPoint(key)
open = ts.get("1. open")
high = ts.get("2. high")
low = ts.get("3. low")
close = ts.get("4. close")
volume = ts.get("5. volume")
dp.addIntraday(open,high,low,close,volume)
dictionary[dp.time] = dp
def getTechnicals(dictionary):
urls = [sma_url, ema_url, vwap_url, macd_url, rsi_url, adx_url]
technicals = ["SMA","EMA","VWAP","MACD","RSI","ADX"]
i = 0
while (i < len(urls)):
response = requests.get(urls[i])
json = response.json()
tech = json.get("Technical Analysis: " + technicals[i])
if (tech == None):
print("Empty response, retrying in 10 seconds...")
time.sleep(10)
else:
print("Getting Technical Indicator: " + technicals[i])
keys = tech.keys()
for key in keys:
t = tech.get(key)
v = t.get(technicals[i])
if (dictionary.get(key) != None):
dictionary.get(key).addTechnical(technicals[i], v)
i += 1
def writeDictionaryToFile(dictionary):
filename = "datapoints.json"
fp = open(filename, "a")
json_dictionary = json.dumps(dictionary)
fp.write(json_dictionary)
print("Wrote results to file: " + filename)
dictionary = {}
getIntraday(dictionary)
getTechnicals(dictionary)
writeDictionaryToFile(dictionary)
Here is the error:
Traceback (most recent call last):
File "/Users/Jason/Dev/Python/neural-network-example/alphavantage.py", line 124, in <module>
writeDictionaryToFile(dictionary)
File "/Users/Jason/Dev/Python/neural-network-example/alphavantage.py", line 113, in writeDictionaryToFile
json_dictionary = json.dumps(dictionary)
File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type DataPoint is not JSON serializable
From my understanding, I can use json.dumps() on a common python datatype, string, int, array dictionary, etc. But I cannot use it on custom objects that I've created. I've done research and from my research, I have figured out to use myCustomObject.dict to make the object serializable. How can I use this when I am trying to serialize the entire dictionary?
I'm new to Python, I just can't figure this out. Any help is greatly appreciated.
It's possible to achieve this using a custom JSON serializer, but that may be overkill for your task. A simpler solution is to give your class a couple of methods to convert to JSON and back, via dictionaries.
Your class has quite a lot of fields, so I'll give a simpler example for a toy class, which you should be able to adapt for your purpose:
import json
class Example:
def __init__(self, x, y):
self.x = x
self.y = y
def to_json(self):
return json.dumps({
'x': self.x,
'y': self.y
})
#classmethod
def from_json(cls, s):
d = json.loads(s)
return cls(d['x'], d['y'])
Usage:
>>> ex = Example(1, 2)
>>> s = ex.to_json()
>>> s
'{"y": 2, "x": 1}'
>>> ex2 = Example.from_json(s)
>>> ex2.x
1
>>> ex2.y
2
json is a very portable format, but it's also restricted. Only the following things can be serialized with Json:
dicts - {} (all keys must be strings)
lists - []
strings - "string"
integers - 0, 1, 2, ...
True
False
None
So you'll have to transform your object to some combination of these things, and have code to transform it back.
If you are planning on ONLY using python, you may be interested in pickle, which can serialize arbitrary python objects, as long as it can import the modules in which they were defined. Do note that unpacking pickles from unknown sources can lead to remote code executions.

TypeError: 'str' object is not callable

This is my code:
class Parser(object):
def __init__(self, inputFile): # initalizer / constructor
#open input file and gets ready to parse it
f = open(inputFile, "r")
self.commands = list(f)
f.close()
print(self.commands)
self.currentCommand = 0
self.index = 0
def hasMoreCommands(self):
#are there any more commands in the input
#returns boolean
if (self.commands[self.currentCommand][self.index] == "\\") and (self.commands[self.currentCommand][self.index+1] == "n"): # checks for "/n", alluding that the command has ended and we can advance to the next command
return True
else:
return False
def advance(self):
#reads next command and makes it current command
#called only if hasMoreCommands is true
if self.hasMoreCommands():
self.currentCommand += 1
def commandType(self):
#returns type of current command A_COMMAND, C_COMMAND, L_COMMAND
#C A or L(psuedo command for (XxX))
#dest=comp; jmp, #, ()
self.type = self.commands[self.currentCommand][0]
if self.type == "#":
return "A_COMMAND"
elif self.type == "(":
return "L_COMMAND"
else:
return "C_COMMAND"
def dest(self):
#returns dest mnemoic of current C instruction - 8 Poss
#called when command type is C
#return string
if (self.commandType() == "C_COMMAND") and ("=" in self.commands[self.currentCommand]):
return self.commands[self.currentCommand][0:(self.commands[self.currentCommand].index("="))]
def main(inputFile):
d = Parser(inputFile)
d.commandType = "C_COMMAND"
d.commands = ["D=A+2\\n", "AMD=A+5\\n"]
d.currentCommand = 0
print(d.dest())
main("/Users/user1/Desktop/filelocation/projects/06/add/add.asm")
The file in question:
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/06/add/Add.asm
// Computes R0 = 2 + 3
#2
D=A
#3
D=D+A
#0
M=D
Error returned:
['// This file is part of www.nand2tetris.org\n', '// and the book "The Elements of Computing Systems"\n', '// by Nisan and Schocken, MIT Press.\n', '// File name: projects/06/add/Add.asm\n', '\n', '// Computes R0 = 2 + 3\n', '\n', '#2\n', 'D=A\n', '#3\n', 'D=D+A\n', '#0\n', 'M=D\n']
Traceback (most recent call last):
File "/Users/user1/Desktop/Python/filelocation/assembler.py", line 104, in <module>
main("/Users/user1Desktop/filelocation/projects/06/add/add.asm")
File "/Users/user1/Desktop/Python/filelocation/assembler.py", line 99, in main
print(d.dest())
File "/Users/user1/Desktop/Python/filelocation/assembler.py", line 50, in dest
if (self.commandType() == "C_COMMAND") and ("=" in self.commands[self.currentCommand]):
TypeError: 'str' object is not callable
[Finished in 0.1s with exit code 1]
I was attempting to test dest.
This is a part of the Nand 2 Tetris / Elements of Computing Systems curriculum at Chapter 6.
In your main, you are replacing the method def commandType(self) with d.commandType = "C_COMMAND", which is a str and therefore cannot be called like a method.
For your class....
class Parser(object):
def __init__(self, inputFile): # initalizer / constructor
#open input file and gets ready to parse it
f = open(inputFile, "r")
self.commands = list(f)
f.close()
You already set self.commands from the file
And note: index and currentCommand appear to serve the exact same purpose
Your function uses that list.
def commandType(self):
#returns type of current command A_COMMAND, C_COMMAND, L_COMMAND
#C A or L(psuedo command for (XxX))
#dest=comp; jmp, #, ()
self.type = self.commands[self.currentCommand][0]
Therefore, you do not need these lines
def main(inputFile):
d = Parser(inputFile)
# d.commandType = "C_COMMAND"
# d.commands = ["D=A+2\\n", "AMD=A+5\\n"]
# d.currentCommand = 0
So you only need this main assuming the input file is correct.
def main(inputFile):
d = Parser(inputFile)
print(d.dest())
Your error is that d.commandType = "C_COMMAND" cannot be "called" by "C_COMMAND()", (i.e. d.commandType())

Categories

Resources