Not able to reach generated lists in other .py file - python

I need some help to solve the problem :
I have two files : "main.py" and let's say "script.py"
The "script.py" contains a func() that generates variable amount of lists (programm uses Database, so amount of lists and data inside is vary):
def func():
try:
connect = psycopg2.connect(database = 'car_rental',
user = 'postgres',
password = 'datapass')
curs = connect.cursor()
#iteration that creates the list contains all models available for every single brand with name '{category}_{brand.lower()}'
# (in this case: economy_{brand.lower()})
temp_var = ''
for brand in economy_brands_list:
curs.execute("""SELECT DISTINCT model
FROM fleet
WHERE category = %s and brand = %s""", ('economy', f'{brand}'))
expres = [x[0] for x in curs.fetchall()]
temp_var+=f"economy_{brand.lower()} = {expres}\n"
exec(temp_var)
finally:
curs.close()
connect.close()
In "main.py" i want to use the list(s) generated in func(). So i imported func() to 'main.py', call the func(), but it gives the error instead.NameError : name 'economy_{brand}' is not defined. From the 'script.py' (which contains func()) the function works and i'm able to print the lists generated. How to make 'main.py' to define the lists generated in func()?
Thank You in advance.

To expand on Tierry Lathuille's answer, you may want something like this:
def func():
economy_brands = {}
try:
connect = psycopg2.connect(database = 'car_rental',
user = 'postgres',
password = 'datapass')
curs = connect.cursor()
#iteration that creates the list contains all models available for every single brand with name '{category}_{brand.lower()}'
# (in this case: economy_{brand.lower()})
temp_var = ''
for brand in economy_brands_list:
curs.execute("""SELECT DISTINCT model
FROM fleet
WHERE category = %s and brand = %s""", ('economy', f'{brand}'))
expres = [x[0] for x in curs.fetchall()]
economy_brands[f"economy_{brand.lower()}"] = expres
finally:
curs.close()
connect.close()
return economy_brands

Related

Use cursor.executemany instead of cursor.execute with tying panda header to sql variables

I have a python script that updates rows in an oracle sql table correctly, however I am using cursor.execute and try/except so if one update fails, it kills the whole run.
I want to be able to have it run through the whole update and just log the error and move onto the next one, which is where cursor.executemany comes in.
https://cx-oracle.readthedocs.io/en/latest/user_guide/batch_statement.html
Here is the script, it works great, except for the all or nothing error approach.
#oracle sql update statement for SHRTCKN
banner_shrtckn_update = """
UPDATE SATURN.SHRTCKN A
SET A.SHRTCKN_COURSE_COMMENT = :course_comment,
A.SHRTCKN_REPEAT_COURSE_IND = :repeat_ind,
A.SHRTCKN_ACTIVITY_DATE = SYSDATE,
A.SHRTCKN_USER_ID = 'STU00940',
A.SHRTCKN_DATA_ORIGIN = 'APPWORX'
WHERE A.SHRTCKN_PIDM = gb_common.f_get_pidm(:id) AND
A.SHRTCKN_TERM_CODE = :term_code AND
A.SHRTCKN_SEQ_NO = :seqno AND
A.SHRTCKN_CRN = :crn AND
A.SHRTCKN_SUBJ_CODE = :subj_code AND
A.SHRTCKN_CRSE_NUMB = :crse_numb
"""
def main():
# get time of run and current year
now = datetime.datetime.now()
year = str(now.year)+"40"
# configure connection strings for banner PROD
db_pass = os.environ['DB_PASSWORD']
dsn = cx_Oracle.makedsn(host='FAKE', port='1521', service_name='TEST.FAKE.BLAH')
try: # initiate banner db connection -- PROD
banner_cnxn = cx_Oracle.connect(user=config.db_test['user'], password = db_pass, dsn=dsn)
writeLog("---- Oracle Connection Made ----")
insertCount = 0
for index, row in df.iterrows():
shrtcknupdate(row,banner_cnxn)
insertCount = insertCount + 1
banner_cnxn.commit()
banner_cnxn.close()
writeLog(str(insertCount)+" rows updated")
except Exception as e:
print("Error: "+str(e))
writeLog("Error: "+str(e))
def writeLog(content):
print(content)
log.write(str(datetime.date.today())+" "+content+"\n")
#define the variable connection between panda/csv and SHRTCKN table
def shrtcknupdate(row, connection):
sql = banner_shrtckn_update
variables = {
'id' : row.Bear_Nbr,
'term_code' : row.Past_Term,
'seqno' : row.Seq_No,
'crn' : row.Past_CRN,
'subj_code' : row.Past_Prefix,
'crse_numb' : row.Past_Number,
'course_comment' : row.Past_Course_Comment,
'repeat_ind' : row.Past_Repeat_Ind
}
cursor = connection.cursor()
cursor.execute(sql, variables)
if __name__ == "__main__":
writeLog("-------- Process Start --------")
main()
writeLog("-------- Process End --------")
The executemany option, I can turn on batcherrors=True
and it will do exactly what I need.
The problem I am running into, is if I get rid of the for loop that runs through the excel/panda dataframe to update the oracle sql rows, which is not needed when doing the update in batch, then how do I attach the column headers to the sql update statement.
If I leave in the for loop, I get this error when using executemany:
Error: parameters should be a list of sequences/dictionaries or an integer specifying the number of times to execute the statement
For named binds, you need to provide a list of dictionaries. This list can be obtained by to_dict(orient='records'):
‘records’ : list like [{column -> value}, … , {column -> value}]
banner_shrtckn_update = """
UPDATE SATURN.SHRTCKN A
SET A.SHRTCKN_COURSE_COMMENT = :Past_Course_Comment,
A.SHRTCKN_REPEAT_COURSE_IND = :Past_Repeat_Ind,
A.SHRTCKN_ACTIVITY_DATE = SYSDATE,
A.SHRTCKN_USER_ID = 'STU00940',
A.SHRTCKN_DATA_ORIGIN = 'APPWORX'
WHERE A.SHRTCKN_PIDM = gb_common.f_get_pidm(:Bear_Nbr) AND
A.SHRTCKN_TERM_CODE = :Past_Term AND
A.SHRTCKN_SEQ_NO = :Seq_No AND
A.SHRTCKN_CRN = :Past_CRN AND
A.SHRTCKN_SUBJ_CODE = :Past_Prefix AND
A.SHRTCKN_CRSE_NUMB = :Past_Number
"""
def main():
# get time of run and current year
now = datetime.datetime.now()
year = str(now.year)+"40"
# configure connection strings for banner PROD
db_pass = os.environ['DB_PASSWORD']
dsn = cx_Oracle.makedsn(host='FAKE', port='1521', service_name='TEST.FAKE.BLAH')
try: # initiate banner db connection -- PROD
banner_cnxn = cx_Oracle.connect(user=config.db_test['user'], password = db_pass, dsn=dsn)
writeLog("---- Oracle Connection Made ----")
# batch execute banner_shrtckn_update
cursor = banner_cnxn.cursor()
data = df[['Bear_Nbr', 'Past_Term', 'Seq_No', 'Past_CRN', 'Past_Prefix', 'Past_Number', 'Past_Course_Comment', 'Past_Repeat_Ind']].to_dict('records')
cursor.executemany(banner_shrtckn_update, data, batcherrors=True)
for error in cursor.getbatcherrors():
writeLog(f"Error {error.message} at row offset {error.offset}")
banner_cnxn.commit()
banner_cnxn.close()
except Exception as e:
print("Error: "+str(e))
writeLog("Error: "+str(e))
This isn't described in detail in the documenation, but you can find an example for named binds in python-cx_Oracle/samples/bind_insert.py.
(Please note that I adjusted the variable names in your sql statement to the dataframe column names to avoid renaming of the columns at creating data.)

List index out of range error for loop on Json

I'm trying to request a json object and run through the object with a for loop and take out the data I need and save it to a model in django.
I only want the first two attributes of runner_1_name and runner_2_name but in my json object the amount or runners varies inside each list. I keep getting list index out of range error. I have tried to use try and accept but when I try save to the model it's showing my save variables is referenced before assignment What's the best way of ignoring list index out or range error or fixing the list so the indexes are correct? I also want the code to run really fast as I will using this function as a background task to poll every two seconds.
#shared_task()
def mb_get_events():
mb = APIClient('username' , 'pass')
tennis_events = mb.market_data.get_events()
for data in tennis_events:
id = data['id']
event_name = data['name']
sport_id = data['sport-id']
start_time = data['start']
is_ip = data['in-running-flag']
par = data['event-participants']
event_id = par[0]['event-id']
cat_id = data['meta-tags'][0]['id']
cat_name = data['meta-tags'][0]['name']
cat_type = data['meta-tags'][0]['type']
url_name = data['meta-tags'][0]['type']
try:
runner_1_name = data['markets'][0]['runners'][0]['name']
except IndexError:
pass
try:
runner_2_name = data['markets'][0]['runners'][1]['name']
except IndexError:
pass
run1_par_id = data['markets'][0]['runners'][0]['id']
run2_par_id = data['markets'][0]['runners'][1]['id']
run1_back_odds = data['markets'][0]['runners'][0]['prices'][0]['odds']
run2_back_odds = data['markets'][0]['runners'][1]['prices'][0]['odds']
run1_lay_odds = data['markets'][0]['runners'][0]['prices'][3]['odds']
run2_lay_odds = data['markets'][0]['runners'][1]['prices'][3]['odds']
te, created = MBEvent.objects.update_or_create(id=id)
te.id = id
te.event_name = event_name
te.sport_id = sport_id
te.start_time = start_time
te.is_ip = is_ip
te.event_id = event_id
te.runner_1_name = runner_1_name
te.runner_2_name = runner_2_name
te.run1_back_odds = run1_back_odds
te.run2_back_odds = run2_back_odds
te.run1_lay_odds = run1_lay_odds
te.run2_lay_odds = run2_lay_odds
te.run1_par_id = run1_par_id
te.run2_par_id = run2_par_id
te.cat_id = cat_id
te.cat_name = cat_name
te.cat_type = cat_type
te.url_name = url_name
te.save()
Quick Fix:
try:
runner_1_name = data['markets'][0]['runners'][0]['name']
except IndexError:
runner_1_name = '' # don't just pass here
try:
runner_2_name = data['markets'][0]['runners'][1]['name']
except IndexError:
runner_2_name = ''
It giving you variables is referenced before assignment because in expect block you are just passing, so if try fails runner_1_name or runner_2_name is never defined. You when you try to use those variables you get an error because they were never defined. So in except block either set the value to a blank string or some other string like 'Runner Does not Exists'.
Now if you want to totally avoid try/except and IndexError you can use if statements to check the length of markets and runners. Something like this:
runner_1_name = ''
runner_2_name = ''
# Make sure markets exists in data and its length is greater than 0 and runners exists in first market
if 'markets' in data and len(data['markets']) > 0 and 'runners' in data['market'][0]:
runners = data['markets'][0]['runners']
# get runner 1
if len(runners) > 0 and `name` in runners[0]:
runner_1_name = runners[0]['name']
else:
runner_1_name = 'Runner 1 does not exists'
# get runner 2
if len(runners) > 1 and `name` in runners[1]:
runner_2_name = runners[1]['name']
else:
runner_2_name = 'Runner 2 does not exists'
As you can see this gets too long and its not the recommended way to do things.
You should just assume data is alright and try to get the names and use try/except to catch any errors as suggested above in my first code snippet.
I had the issue with a list of comments that can be empty or filled by an unknown number of comments
My solution is to initialize a counting variable at 0 and have a while loop on a boolean
In the loop I try to get comment[count] if it fails on except IndexError I set the boolean to False to stop the infinite loop
count = 0
condition_continue = True
while condition_continue :
try:
detailsCommentDict = comments[count]
....
except IndexError:
# no comment at all or no more comment
condition_continue = False

Python3.6 function not called

I'm developing a REST API in Python 3.6 using Flask-Rebar and PostgreSQL and am having trouble trying to execute some queries simultaneously using psycopg2.
More specifically, I execute a query and require the id value from this query for use in the next query. The first query successfully returns the expected value, however the function that calls the subsequent query doesn't even execute.
Here is the function responsible for calling the query function:
psql = PostgresHandler()
user_ids = [1, 5, 9]
horse = {"name": "Adam", "age": 400}
def createHorseQuery(user_ids, horse):
time_created = strftime("%Y-%m-%dT%H:%M:%SZ")
fields, values = list(), list()
for key, val in horse.items():
fields.append(key)
values.append(val)
fields.append('time_created')
values.append(time_created)
fields = str(fields).replace('[', '(').replace(']', ')').replace("'", "")
values = str(values).replace('[', '(').replace(']', ')')
create_horse_query = f"INSERT INTO horse {fields} VALUES {values} RETURNING horse_id;"
horse_id = None
for h_id in psql.queryDatabase(create_horse_query, returnInsert=True):
horse_id = h_id
link_user_query = ''
for u_id in user_ids:
link_user_query += f"INSERT INTO user_to_horse (user_id, horse_id) VALUES ({u_id}, {horse_id['horse_id']});"
psql.queryDatabase(link_user_query)
return horse_id, 201
Here is the PostgresHandler() class that contains the function queryDatabase:
class PostgresHandler(object):
def __init__(self):
self.connectToDatabase()
def connectToDatabase(self):
self.connection = psycopg2.connect(
host = '...',
user = '...',
password = '...',
database = '...'
)
def queryDatabase(self, query, returnInsert=False):
cursor = self.connection.cursor(cursor_factory=RealDictCursor)
cursor.execute(query)
if "SELECT" in query.upper():
for result in cursor.fetchall():
yield result
elif "INSERT" in query.upper():
if returnInsert:
for result in cursor.fetchall():
yield result
self.connection.commit()
cursor.close()
I can verify that the psql.queryDatabase(create_horse_query, returnInsert=True) operation is successful by querying the database manually and comparing against the return value, h_id.
I can verify that link_user_query is created and contains the user_ids and horse_id as expected by printing. I know the query that's generated is okay as I have tested this manually in the database.
It appears that the function called on the line psql.queryDatabase(link_user_query) is never actually called as a print statement at the very top of the queryDatabase function does not get executed.
I've tried with delays between the two query function calls, initialising a new connection with each function call and many other things to no avail and I am absolutely stumped. Any insight is greatly appreciated.
EDIT: FYI, The createHorseQuery function returns successfully and displays the two returned values as expected.
queryDatabase in your code is a generator because it contains a yield statement. The generator only actually does things when you iterate over it (i.e. cause __next__() to be called). Consider the following:
def gen():
print("Gen is running!")
yield "Gen yielded: hello"
print("Gen did: commit")
print("***Doing stuff with b***")
b = gen()
for a in b:
print(a)
print("***Doing stuff with c***")
c = gen()
print("***Done***")
Output is:
***Doing stuff with b***
Gen is running!
Gen yielded: hello
Gen did: commit
***Doing stuff with c***
***Done***
When we called gen() to create c we didn't actually run it, we just instantiated it as a generator.
We could force it to run by calling __next__() on it a bunch of times:
c.__next__()
try:
c.__next__()
except StopIteration:
print("Iteration is over!")
outputs:
Gen is running!
Gen did: commit
Iteration is over!
But really, you should probably not use a generator like this where you are never intending to yield from it. You could consider adding a new function which is not a generator called insertSilently (or similar).

Python script writes twice in to the tables

I am trying to automate this scenario. I have 2 .sql files (add1.sql and add2.sql) which has 1 insert script each.
My goal is to write one record to table1 by executing lines from add1.sql and one record to cm.cl by executing lines from add2.sql, waiting for about 5 mins so a backend service runs. This service writes from DB1 to DB2. I then connect to DB2 to see if the record from DB1 matches what was written to DB2. Depending no the results, an email is sent.
Below is my code. Everything works just fine except that it writes twice to DB1. So, basically 4 records are inserted instead of 2. Any idea why it writes 4 records?
import pypyodbc as pyodbc
import smtplib
sender = 'abc#abc.com'
receivers = ['abc#abc.com','xyz#abc.com']
import unittest
import time
class TestDB1(unittest.TestCase):
def testing_master(self):
Master_Conn = 'Driver=
{SQLServer};Server=server\servername;Database=database;UID=userid;PWD=password'
Master_db = pyodbc.connect(Master_Conn)
Master_Cursor = Master_db.cursor()
try:
#Open, read and execute add_shell.sql
file = open('C:\\aaa\\add1.sql', 'r')
line = file.read()
lines = line.replace('\n', ' ')
file1 = open('C:\\aaa\\add2.sql', 'r')
line1=file1.read()
lines1=line1.replace('\n', ' ')
Master_Cursor.execute(lines)
time.sleep(1)
Master_Cursor.execute(lines1)
Master_db.commit()
file.close()
file1.close()
#Get python object for latest record inserted in DB1
Master_CID=Master_Cursor.execute("select col1 from tablename1 order by sequenceid desc").fetchone()
#convert tuple to srting [0] gives first tuple element.
Master_CID_str=str(Master_CID[0])
#Get GUID by stripping first 2 chars and last char.
Master_CID_str=Master_CID_str[2:len(Master_CID_str)-1]
Master_CLID=Master_Cursor.execute("select col2 from tablename2 order by sequenceid desc").fetchone()
Master_CLID_str=str(Master_CLID[0])
Master_CLID_str=Master_CLID_str[2:len(Master_CLID_str) - 1]
# Wait for service that transfers data from one db to another DB to run
time.sleep(310)
finally:
Master_Cursor.close()
Master_db.close()
return Master_CID,Master_CID_str,Master_CLID,Master_CLID_str
def testing_int_instance(self):
#unpacking return value of tuple from testing_master() function
Master_CID,Master_CID_str,Master_CLID,Master_CLID_str=self.testing_master()
print ("printing from testing_int_instance {0}".format(Master_CID))
Int_Instance_Conn = 'Driver={SQL Server};Server=server2\servername2;Database=database2;UID=uid;PWD=password;'
Int_db = pyodbc.connect(Int_Instance_Conn)
Int_Cursor = Int_db.cursor()
#return Int_db, Int_Cursor
#execute select from db where col matches that of one inserted in master db.
Int_Instance_CID=Int_Cursor.execute("select col1 from table1 where cartridgemodelid = '%s'" %(Master_CID_str)).fetchone()
print(Int_Instance_CID)
smtpObj = smtplib.SMTP('22.101.1.333', 25)
if (Master_CID==Int_Instance_CID):
print("Matched")
content="This email confirms successful data transfer from Master to Instance for col1: \n"
message = "\r\n".join(["From:" + sender,"To:" + str(receivers[:]),"Subject: Test Result","",content +Master_CID_str])
#smtpObj = smtplib.SMTP('22.101.2.222', 25)
smtpObj.sendmail(sender, receivers, message)
elif (Master_CID!=Int_Instance_CID):
print("no match")
content = "This email confirms failure of data transfer from DB1 to DB2 for COL1: \n"
message = "\r\n".join(["From:" + sender, "To:" + str(receivers[:]), "Subject: Test Result", "",content +Master_CID_str])
smtpObj.sendmail(sender, receivers, message)
Int_Instance_CLID=Int_Cursor.execute("select COL2 from table2 where col= '%s'" %(Master_CLID_str)).fetchone()
print (Int_Instance_CLID)
if (Master_CLID == Int_Instance_CLID):
print ("Printing int_instance CLID {0}".format(Int_Instance_CLID))
content = "This email confirms successful data transfer from DB1 to DB2 for COL: \n"
message = "\r\n".join(
["From:" + sender, "To:" + str(receivers[:]), "Subject: Test Result", "", content + Master_CLID_str])
#smtpObj = smtplib.SMTP('22.101.2.222', 25)
smtpObj.sendmail(sender, receivers, message)
print ("Ids Matched")
elif (Master_CLID != Int_Instance_CLID):
DB1 to DB2 for COL: \n"
message = "\r\n".join(
["From:" + sender, "To:" + str(receivers[:]), "Subject: Test Result", "", content + Master_CLID_str])
#smtpObj = smtplib.SMTP('22.101.2.222', 25)
smtpObj.sendmail(sender, receivers, message)
smtpObj.quit()
Int_db.close()
if name == 'main':
unittest.main()
add1.sql is:
DECLARE #Name VARCHAR(2000)
DECLARE #PartNumber VARCHAR(2000)
SELECT #Name='test'+convert(varchar,getdate(),108)
SELECT #PartNumber='17_00001_'+convert(varchar,getdate(),108)
DECLARE #XML XML
DECLARE #FileName VARCHAR(1000)
DECLARE #Id UNIQUEIDENTIFIER
SELECT #Id = NEWID()
SELECT #FileName = 'test.xml'
SELECT #XML='<model>
<xml tags go here>
BEGIN
INSERT INTO table1
(ID,Name,Type,Desc,Number,Revision,Model,status,Modifiedby,Modifiedon)
VALUES(#Id,#Name,'xyz','',#partnumber,'01',#XML,'A','453454-4545-4545-4543-345342343',GETUTCDATE())
add2.sql is:
DECLARE #XML XML
DECLARE #CM_Name VARCHAR(2000)
DECLARE #FileName VARCHAR(1000)
DECLARE #PartNumber VARCHAR(2000)
DECLARE #Id UNIQUEIDENTIFIER
SELECT #Id=NEWID()
DECLARE #Name VARCHAR(2000)
DECLARE #CMId VARCHAR(2000)
DECLARE #CM_PartName VARCHAR(2000)
DECLARE #CM_Partnumber VARCHAR(2000)
SELECT #Name='test'+convert(varchar,getdate(),108)
SELECT #PartNumber='test'+convert(varchar,getdate(),108)
DECLARE #RowCount INT
DECLARE #Message VARCHAR(100);
SELECT #FileName = 'test.xml'
SELECT #CMId = CM.CMID,
#CM_Name = CM.CMName,
#CM_PN = CM.PN
FROM cm.Model CM
WHERE CM.MName LIKE 'test%'
ORDER BY CM.ModifiedBy DESC
SELECT #XML='<Layout>
other xml tags...
BEGIN
INSERT INTO cm.CL(ID, ModelID, Layout, Description, PN, Revision, CLayout, Status, ModifiedBy, ModifiedOn)
SELECT TOP 1 #Id, #CMId, #Name, '', #PartNumber, '01', #XML, 'A', '453454-345-4534-4534-4534543545', GETUTCDATE()
FROM cm.table1 CM
WHERE CM.Name=#CM_Name
AND CM.Partnumber=#CM_Partnumber
Currently, you are calling test_master() twice! First as your named method and then in second method when you unpack the returned values. Below is a demonstration of defined methods outside of the Class object. If called as is, testing_master will run twice.
Consider also using a context manager to read .sql scripts using with() which handles open and close i/o operations shown below:
# FIRST CALL
def testing_master():
#...SAME CODE...
try:
with open('C:\\aaa\\add1.sql', 'r') as file:
lines = file.read().replace('\n', ' ')
Master_Cursor.execute(lines)
Master_db.commit()
time.sleep(1)
with open('C:\\aaa\\add2.sql', 'r') as file1:
lines1 = file1.read().replace('\n', ' ')
Master_Cursor.execute(lines1)
Master_db.commit()
#...SAME CODE...
return Master_CID, Master_CID_str, Master_CLID, Master_CLID_str
def testing_int_instance():
# SECOND CALL
Master_CID, Master_CID_str, Master_CLID, Master_CLID_str = testing_master()
#...SAME CODE...
if __name__ == "__main__":
testing_master()
testing_int_instance()
Commenting out the time(310) seems like it works but as you mention the background Windows service does not effectively run and so interrupts database transfer.
To resolve, consider calling the second method at the end of the first by passing the values as parameters without any return and remove unpacking line. Then, in the main global environment, only run testing_master(). Of course qualify with self when inside a Class definition.
def testing_master():
#...SAME CODE...
testing_int_instance(Master_CID, Master_CID_str, Master_CLID, Master_CLID_str)
def testing_int_instance(Master_CID, Master_CID_str, Master_CLID, Master_CLID_str):
#...SKIP UNPACK LINE
#...CONTINUE WITH SAME CODE...
if __name__ == "__main__":
testing_master()
Due to your unittest, consider slight adjustment to original setup where you qualify every variable with self:
def testing_master():
...
self.Master_CID=Master_Cursor.execute("select col1 from tablename1 order by sequenceid desc").fetchone()
self.Master_CID_str=str(Master_CID[0])
self.Master_CID_str=Master_CID_str[2:len(Master_CID_str)-1]
self.Master_CLID=Master_Cursor.execute("select col2 from tablename2 order by sequenceid desc").fetchone()
self.Master_CLID_str=str(Master_CLID[0])
self.Master_CLID_str=Master_CLID_str[2:len(Master_CLID_str) - 1]
def testing_int_instance(self):
# NO UNPACK LINE
# ADD self. TO EVERY Master_* VARIABLE
...

Creating a Table(array) of Records

If I wanted to store records from two files into a table (an array of records), could I use a format similar to the below code, and just put both file names in def function like def readTable(log1,log2): and then use the same code for both log1 and log2 allowing it to make a table1 and a table2?
def readTable(fileName):
s = Scanner(fileName)
table = []
record = readRecord(s)
while (record != ""):
table.append(record)
record = readRecord(s)
s.close()
return table
Just use *args, and get a list of records?
def readTable(*args):
tables = []
for filename in args:
s = Scanner(fileName)
table = []
record = readRecord(s)
while (record != ""):
table.append(record)
record = readRecord(s)
s.close()
tables.append(table)
return tables
This way, you can pass log1, log2, log3 (any number of logs you like and get back a list of tables for each
Since readTable returns a list, if you want to concatenate the records from 2 logs, use the + operator.
readTable(log1) + readTable(log2)

Categories