I have a problem trying to access a variable from file a.py from a function in file b.py. I tried looking around the internet and could not find anything, or I don't know exactly how to look for what I need. I also tried to make another file and update the variable in file c.py, but file b.py still see's the first initialization of the variable. I tried to update the variable in file a.py and afterwards import a.py in the function in b.py.
File a.py
var = []
def run():
a.welcome()
while True:
menu = a.menu()
if menu == 1:
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
var.append(line)
if __name__ == "__main__":
run()
file b.py
I tried like this but I get the first initialization of the variable var = []
I first updated var from file a.py and afterwards, I tried to use the function below inside file b.py but still the same result.
from a import var
from a import *
import a
def a_function():
from a import var
from a import *
import a
print(var)
print(a.var)
This prints the first initialization of var which = [] not after it was appended.
If I print var from a, from inside the function it prints it updated.
If I print var from a, from outside the function it prints it updated.
What I don’t understand is, why after updating it, and importing it into b, I still get the first initialization. Debugger didn’t help as well. I can work around it by adding the function retrieve_path inside b.py and then appending the data in another variable inside file b.py but I would like to know why its not importing var updated with the data.
File b.py
var2 = []
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
var.append(line)
var2.append(line)
The reason I didn't use Class if that was one of the solutions, is because I haven't learned that much about Classes and don't know how to use them properly for the time being.
I hope I was quite explicit and you understand my dilemma. Also, have in mind I just started learning Python, so a newbi explanation and solution are more than welcomed.
CodePudding user response:
The correct way is to call the run
function before accessing var
. Either
import a
a.run
print(a.var)
or:
from a import var, run
run
print(var)
The import
statement only runs the content of the module, not the functions declared in it.
The idiomatic way of running a script is indeed what you have in a.py:
if __name__ == "__main__":
run()
And the run
function will be called if you use the file like a script with python a.py
, because a file that is started directly by the interpretor will be named __main__
. But when it is imported, it is named according to the file name. So here it would be a
and not main
. Said differently, run
is never called when a.py
is imported.
One possibility would be to end a.py with an unconditional call of run
:
...
line = list(line)
var.append(line)
run()
It should be harmless because Python keeps track of the already imported module, and run
should be called only once even if the module was imported from multiple places. Yet it would be an anti-pattern, because by convention import should have as few side effects as possible, while run seems to do plenty of actions.
CodePudding user response:
Ok, this is just a part of the project which was for the school, which I finished, but I wanted to make this part with records a little bit different than I've done for the grade. If some function dont make sense, its because the project it is not finished. My only concerned is towards records variable.
main.py
import tui, csv
records = []
def run():
tui.welcome()
while True:
menu = tui.menu()
if menu == 1:
def retrieve_path(source_path):
"""The function takes 1 parameter and checks if the file name exist as well as the file path
Adds the csv data to a variable
source_path (str): Path against whom to check for validity
"""
if not source_path:
print("Invalid file name, Please try again\n")
return
else:
import os
isFile = os.path.isfile(source_path)
if not isFile:
print("Invalid file path\n")
return
else:
with open(source_path, "r") as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
for line in csv_reader:
line = list(line)
records.append(line)
tui.started("Data Loading")
retrieve_path(tui.source_data_path())
tui.completed("Data Loading")
if menu == 2:
tui.started("Retrieving data")
process_menu = tui.process_type()
tui.completed("Retrieving data")
if process_menu == 1:
tui.started("Retrieving entity name")
tui.entity_name()
tui.completed("Retrieving entity name")
if process_menu == 2:
tui.started("Retrieving entity details")
entity, cols = tui.entity_details()
tui.list_entity(entity, cols)
tui.completed("Retrieving entity details")
if menu == 3:
print(tui.main_records)
if menu == 4:
break
if __name__ == "__main__":
run()
Second file is:
tui.py
def welcome():
message = "System Management"
print("*" * len(message))
print(message)
print("*" * len(message))
def menu():
main_menu = "-"
while main_menu != "0":
if main_menu == "-":
print('Main Menu:'
'\n1. Load Data'
'\n2. Process Data'
'\n3. Visualise Data'
'\n4. Save Data'
'\n0. Exit')
elif main_menu in "1234":
return int(main_menu)
elif main_menu not in "1234":
error(main_menu)
return None
else:
print('Main Menu:'
'\n1. Load Data'
'\n2. Process Data'
'\n3. Visualise Data'
'\n4. Save Data'
'\n0. Exit')
main_menu = input()
def started(operation):
print("{} has started.\n".format(operation))
def completed(operation):
print("{} has completed.\n".format(operation))
def error(error_msg):
print("Error! {} is not a valid option.".format(error_msg))
def source_data_path():
print("Please enter the path to the source data file:")
source_path = input()
if ".csv" not in source_path:
return None
else:
return source_path
def process_type():
process_menu = "-"
while process_menu != "0":
if process_menu == "-":
print('Process Menu:'
'\n1. Retrieve entity'
'\n2. Retrieve entity details'
'\n3. Categorise entities by type'
'\n4. Categorise entities by gravity'
'\n5. Summarise entities by orbit'
'\n6. Return to Main Menu')
elif process_menu == "6":
menu()
return None
elif process_menu in "12345":
return int(process_menu)
elif process_menu not in "12345":
error(process_menu)
return None
else:
print('Process Menu:'
'\n1. Retrieve entity'
'\n2. Retrieve entity details'
'\n3. Categorise entities by type'
'\n4. Categorise entities by gravity'
'\n5. Summarise entities by orbit'
'\n6. Return to Main Menu')
process_menu = input()
def entity_name():
entity = input("Please enter the name of an entity: ")
return entity
def entity_details():
entity = input("Please enter the name of an entity: ")
indexes = input("Please enter the indexes number (e.g. 0,1,5,7):\n")
return entity, list(indexes)
Please have First time I did the project I added def retrieve_path(source_path): to tui.py and it worked fine.
What I don't really understand is why is the variable records being appended to, I can print it from within run and outside of run function, but in tui.py i get only records = [] and how to solve this without creating the function retrieve_path in tui.py
This is what it was asked of us at the time being and it was not my personal choice to do it like this.
I am sorry for not pasting everything here and mistyping some parts like == _ main _ .