i have a irrational error,
code:
#====================================================#
#X Programming Language 2022(for Jadi) License: GPL #
#====================================================#
from os import system #importing system func. for cmd
code_location = "" #saving code location in this
code = "" #saving code in this
def main(): #main func.
code_location = input() #get code location from user
code = get_code() #cal get_code and save res to code var
print(code) #print code
end() #calling end
def get_code(): #get_code func. for getting code from file
code_file = open(code_location, 'r') #openning file with method read and saving to code_file
res = code_file.readlines() #saving the content from file to res
return res #returning res
def compiler(): #compiler func. for compiling code
pass
def end(): #when program end...
input("Press Enter to Countinue...")
if __name__ == "__main__":
main()
and this is code directory:
enter image description here
running:
enter image description here
Short answer: Your two code_location variables are not the same thing.
Variable scopes
Variables have a property called a scope, which is essentially which context they belong to. Unless specified otherwise, variables within a function exist only within that function. Consider:
a = 0
def set_a():
a = 1
set_a()
print(a)
This will print 0. This is because the a variable within the function set_a is actually a different variable to the a defined in line 1. Although they have the same name, they point to different places in memory.
Solutions
There are a few ways to do this:
Defining scope
Either, you can set the scope of a within the function to global (instead of local). What this does is now, instead of a within the function pointing to a different memory location, it points to the same memory location as a outside the variable. This is done like so:
a = 0
def set_a():
global a
a = 1
set_a()
print(a)
In this case, a will be set to 1, and "1" will be printed
Passing as an argument
Another way to do this, and may be more relevant in your circumstance, is to pass the value as a variable to the function. In your case, you are using code_location as the file path, so therefore what you want to pass code_location into the function. You would then have to define your function like this:
def get_code(code_location):
and call the function (from your main function) like this:
code = get_code(code_location)
Notes
When operating on files, it is best practice to use a with block. This handles closing your file when you are done with it, and can prevent corruption of files in the rare case that something goes wrong with your code. This can be done like this:
with open(code_location, 'r') as code_file:
res = code_file.readlines()
return res
Python global variables are read-only in local scopes (e.g. your function's scope) by default.
So in the line code_location = input() you are essentially creating a new new local variable of the same name and assigning the input to it.
In order to write to your global variable instead, you first have to declare your intention:
def main(): #main func.
global code_location # DECLARE WRITE INTENTION FOR GLOBAL
code_location = input() #get code location from user
code = get_code() #cal get_code and save res to code var
print(code) #print code
end() #calling end
You don't have to do the same thing in get_code() since you are only reading from code_location there.
PS:
As was alluded to in the comment, it's good practice to close opened files after you've finished with them:
def get_code(): #get_code func. for getting code from file
code_file = open(code_location, 'r') #openning file with method read and saving to code_file
res = code_file.readlines() #saving the content from file to res
code_file.close() # CLOSE FILE
return res #returning res
Or have it done automatically by a context manager:
def get_code(): #get_code func. for getting code from file
with open(code_location, 'r') as code_file: #openning file with method read and saving to code_file
res = code_file.readlines() #saving the content from file to res
return res #returning res
Related
beginner Python user here.
So, I´m trying to make a program that orders the files of my (many) Downloads folder.
I made a class object to work with the many folders:
class cContenedora:
def __int__(self, nCarp, dCarp): #nCarp Stands is the file name and dCarp Stands for file directory.
self.nCarp = nCarp
self.dCarp = dCarp
So, y wrote a instance like this:
Download = cContenedora()
Download.nCarp = "Downloads/"
#The side bar is for making a path to move my archives from with shutil.move(path, dest)
Download.dCarp = "/Users/MyName/Download/"
#This is for searching the folder with os.listdir(Something.dCarp)
Then, I wrote my function, and it goes something like this:
def ordenador(carpetaContenedora, formato, directorioFinal): #carpetaContenedora is a Download Folder
carpetaContenedora = cContenedora() #carpetaContenedora one of the class objects
dirCCont = os.listdir(carpetaContenedora.dCarp) #The to directory is carpetaContenedora.cCarp
for a in dirCCont:
if a.endswith(formato):
path = "/Users/Aurelio Induni/" + carpetaContenedora().nCarp + a
try:
shutil.move(path, directorioFinal)
print(Fore.GREEN + a + "fue movido exitosamente.")
except:
print(Fore.RED + "Error con el archivo" + a)
pass
for trys in range(len(listaCarpetasDestino)-1): #Is a list full of directories.
for container in listaCarpetasFuente: #A short list of all my Downloads Folder.
for formatx in listaFormatos: #listaFormatos is a list ful of format extensions like ".pdf"
#try: #I disabled this to see the error istead of "Error Total"
ordenador(container, formatx, listaCarpetasDestino[trys])
#except:
#print(Fore.RED + "Error Total") #I disabled this to see the error.
But every time I run it I get the following:
AttributeError: 'cContenedora' object has no attribute 'dCarp'
It says the error is in line 47 (the one with the os.listdir(carpetaContenedora.dCarp))
I´m sure is something small. Python is so amazing, but it also can be so frustrating not knowing what´s wrong.
There is a spelling mistake in the initialization of your instance. It should be "init" instead of "int".
In the class cContenedora, the function should be
class cContenedora:
def __init__(self, nCarp, dCarp):
self.nCarp = nCarp
self.dCarp = dCarp
Additionally, When you are passing in the parameter. Make sure to pass in both of the parameters in the line with Value.
CContenedora(nCarp="something",dCarp="something")
Your class initializer, i.e., __init__() function has 2 parameters nCarp and dCarp but when you are actually creating the object there are no parameters passed.
Your function ordenador takes the first parameter as carpetaContenedora, on the first line same variable is assigned a new object of cContenedora, at this line the original values you passed are lost forever.
This could be the reason it is giving for the error.
Refer this link for more details on how to create classes and instantiate the object.
I am simply trying to add a counter around my for loop, to count how many files are in my directory per qualification of the contains 'VCCS'... the logic is working for the iterating, as it's iterating through my directory the amount of times I have a file in... however my counter keeps reporting 1. Relevant lines are files_in_directory market with comment # here.
I am getting this warning in PyLint: Constant name "files_in_directory" doesn't conform to UPPER_CASE naming stylepylint(invalid-name) , on files_in_directory = 0
I've tried moving the set 0, above the for and try, any thoughts?
if __name__ == "__main__":
try:
currentDT = datetime.datetime.now()
files_in_directory = 0 # here
for filename in os.listdir(config.DIRECTORY_LOCATION):
if filename.__contains__('VCCS'):
old_stdout = sys.stdout
log_file = open("./logs/metrics.log","w")
sys.stdout = log_file
files_in_directory += 1 # here
PENDING_RECORDS = FindPendingRecords().get_excel_data()
# Do operations on PENDING_RECORDS
# Reads excel to map data from excel to vital
MAP_DATA = FindPendingRecords().get_mapping_data()
# Configures Driver
VITAL_ENTRY = VitalEntry()
# Start chrome and navigate to vital website
VITAL_ENTRY.instantiate_chrome()
# Begin processing Records
VITAL_ENTRY.process_records(PENDING_RECORDS, MAP_DATA)
print(f"Date: ")
print (str(currentDT))
print(f"Files in Directory #{files_in_directory}") # here
sys.stdout = old_stdout
log_file.close()
except Exception as exc:
# print(exc)
raise
Note: This is to take place of many comments in the interest of readability
Your question as it sits is not an MCVE. To make it more succinct and to identify the exact cause:
import os
if __name__ == "__main__":
# Remove try block, just let it raise an error
my_counter = 0
for file in os.listdir("some_directory"):
# you don't need to call the __contains__ method
# as the 'in' keyword will invoke that for you
if "VCCS" in file:
# increment your counter first
my_counter += 1
print(file, my_counter)
Now there is no question what is modifying my_counter, and this will print out the file you are looking at, alongside the counter.
Once you've ironed out that behavior, you can start adding in your other functions
import os
if __name__ == "__main__":
# Remove try block, just let it raise an error
my_counter = 0
for file in os.listdir("some_directory"):
if 'VCCS' in file:
my_counter += 1
print(my_counter, file)
# Add functions back in one by one
PENDING_RECORDS = FindPendingRecords().get_excel_data()
Continue this process until you identify what is causing your behavior. As it stands, I don't see anything explicit that could be overwriting that counter variable, so I suspect that either A) the code you posted does not reflect what is being run or B) you are modifying/resetting files_in_directory somewhere else in the module.
Suggested Edit:
I would recommend you add in the other code from your module to see what's going on. That way we have a clearer picture of what's happening as your code runs
So first thing first: you're sure you're passing the right directory, and that this directory contains indeed more than one file containing VCCS in their filename ?
I would also try to run this code without the Try/Except block, to see if you don't get some error after your first increment.
LMK what you get, I hope this helps.
I have a text file I am using as a calibration file for a rudder indicator I am making. (It stores the port and stbd limits and the center position)
I would like to call this file when the program is booted so it had the same calibration settings from previously.
I can store the 3 numbers as a str in a .txt file and know how to recall them as a list.
My thought is to run a function when the app starts defining each part of the list as a variable eg.
calibrationfile1 = open('calfile.txt','r')
lines = calibrationfile1.readlines()
calvalue1 = lines[0].replace(",","").replace("[","").replace("]","")
calvalue = calvalue1.split()
rudderlimits = calvalue
port_rudder_limit = rudderlimits[0]
stbd_rudder_limit = rudderlimits[1]
center_position = rudderlimits[2]
how do I do call this in a function at startup and make the variables available in another function I dont want to use 'global'?
I have already made a funciton that is a calibration that creates this calfile.txt and it works.
thanks for your help :)
you can load the file on the app on_start method
class YourApp(App):
def on_start(self):
self.calibration_data = your_file_loading_function() # returns a dict?
... # other places in your code
class Popcorn(Widget):
def on_callback(self):
port_rudder_limit = App.get_running_app().calibration_data['port_rudder_limit']
... # do something....
or from kv file
<MyWidget>:
port_rudder_limit: app.calibration_data['port_rudder_limit']
I am writing a Python program that responds to request and vocalizes a response back to the user. Below is a sample of two functions. How can I do this without using a global variable and still get back a non-repeating, random response?
# stores prior response
website_result = 'first_response.wav'
def launch_website():
# if service is offline return with default msg otherwise launch service
if is_connected() == 'FALSE':
arg = 'this_service_is_offline.wav'
return arg
else:
site = 'http://www.somesite.com'
launch_it(site)
return launch_website_response()
def launch_website_response():
# using the global variable inside function
global website_result
# possible responses
RESPONSES = ['first_response.wav', 'second_response.wav', 'third_response.wav']
# ensures a non-repeating response
tmp = random.choice(RESPONSES)
while website_result == tmp:
tmp = random.choice(RESPONSES)
website_result = tmp
return website_result
Your website_result variable indicates that you to have some sort of persistent state. Maybe you could consider storing it in a text file and access it everytime you need it and change it afterward (this works if you don't have to do too many calls to it, otherwise you will get in I/O limitations).
I don't know about the specifics of your application, but it might happen that you could also make your two functions take website_result as an argument as suggested by #JGut.
I'm trying to make a game engine in Python as a "weekend project" but I have a problem.
I'm trying to make it that a user can declare a keybind by typing the key and the function into a text file what they want to run but when I run the code from that sheet with exec it runs the function and I have no idea on how to call the function through the variable. (Also I don't want it to run the function when it runs the code.)
Here is the code I use for executing the code from binds.zdata
for line in bind:
try:
exec line
except:
try:
error.write(localtime + " : " + "ERROR: Could not bind key from the bind file : " + line)
except:
pass
Here's the text in binds.zdata
_w = Functions.motion.move().forward()
_a = Functions.motion.move().left()
_s = Functions.motion.move().back()
_d = Functions.motion.move().right()
You want to lose the () at the end of each line:
_w = Functions.motion.move().forward
_a = Functions.motion.move().left
_s = Functions.motion.move().back
_d = Functions.motion.move().right
now you can call the function through the variable by simply applying parenthesis, such as:
_w()
I'm not sure I recommend "exec" since somebody could put any code in there.
But here is your problem.
_w = Functions.motion.move().forward()
Calls the function 'forward' and puts the results in _w.
_w = Functions.motion.move().forward
Assigns the function 'forward' to the variable '_w'.
Since you asked what I would do, I would create a set of tokens that represent the various functions and then let them do the mapping in side a config file (see: ConfigParser). Then parse the config file. It is a little more work, but a lot more secure.
I'd first change the lines in the binds.zdata file like this so they assign a function to each of the variables:
_w = Functions.motion.move().forward
_a = Functions.motion.move().left
_s = Functions.motion.move().back
_d = Functions.motion.move().right
Then, assuming that Functions is defined, I'd execute all the lines in the file at once with something like:
try:
execfile('binds.zdata')
except Exception as exc:
error.write(localtime + " : " + "ERROR: executing binds file")
Afterwards, the _w, _a, _s, _d variables will have the desired function assigned to them, which you can call as usual — i.e. _w(), _a(), etc.
Reading the config like that with exec is going to open you to all kinds of pain at runtime, as the user's config file is going to be executable code that you are just trusting. Malicious or unintentionally just bad commands will get execute. You could template it like this:
def read_config(config_file):
user_button_map = {}
with open(config_file, 'r') as fh:
for line in fh.readlines():
key,func_key = line.strip().split(',')
assert(key in BUTTON_MAP_FUNCTIONS),"no such action"
user_button_map[key] = BUTTON_MAP_FUNCTIONS[func_key]
return user_button_map
BUTTON_MAP_FUNCTIONS = {
"forward" : Functions.motion.move().forward,
"left" : Functions.motion.move().left,
# etc...
}
# sample config file
# w, forward
# a, left
# etc...