I've made a button that creates a txt file and I wanted to make it so that their names are "test1.txt", "test2.txt", "test3.txt", ... and the number would change everytime you create a new file, but it keeps setting it back to 1.
here's my code:
def createtxt(txtfile_number):
filename = "test" + str(txtfile_number) + ".txt"
open(filename, "w")
txtfile_number += 1
print(txtfile_number)
def createtxt_Launch():
createtxt(txtfile_number)
[...]
txtfile_number = 1
createTxtFile_button = Button(menu, text="Create txt file", width=15, command=createtxt_Launch)
I know theproblem is because of the line "txtfile_number = 1" but I don't know how to make it so that it only runs that command once
I'm assuming you're creating your button in the global scope (i.e. not inside a function or method or a module that's different from the one createtxt is in).
Make txtfile_number a global value, and increment it in createtxt_Launch instead of in createtxt.
def createtxt(number):
filename = "test" + str(number) + ".txt"
open(filename, "w")
print(number)
def createtxt_Launch():
global txtfile_number
createtxt(txtfile_number)
txtfile_number += 1
Related
I am working on a system that generates a language for use in fantasy storytelling and need a Markov Generator for it. I was able to find an open source Markov Generator in Python, and modify it to work for one word at a time. Problem is I don't need it to process one word once. I need it to make ~400 unique words, and push the output to a text file with one word per line so my main program can just run the.py, wait a bit, then continue on its merry day after loading the python file's output into memory.
In my normal programming language, I could just make the Markov a subroutine, then set up a loop like this:
set loop=400
:1
call Markov
set /a math=%loop%-1
set loop=%math%
if %loop% gtr 0 goto 1
Nice, simple, easy, intuitive. As long as the subroutine prints to the file, this works no problem, and I can execute it an arbitrary number of times.
Here is my code so far.
#Reads input.txt into an array.
def readFile(input):
fileObj = open(input, "r") #opens the file in read mode
words = fileObj.read().splitlines() #puts the file into an array
fileObj.close()
#Creates new words using input.txt as a seed.
class Mdict:
def __init__(self):
self.d = {}
def __getitem__(self, key):
if key in self.d:
return self.d[key]
else:
raise KeyError(key)
def add_key(self, prefix, suffix):
if prefix in self.d:
self.d[prefix].append(suffix)
else:
self.d[prefix] = [suffix]
def get_suffix(self,prefix):
l = self[prefix]
return random.choice(l)
class MName:
"""
A name from a Markov chain
"""
def __init__(self, chainlen = 2):
"""
Building the dictionary
"""
if chainlen > 10 or chainlen < 1:
print ("Chain length must be between 1 and 10, inclusive")
sys.exit(0)
self.mcd = Mdict()
oldnames = []
self.chainlen = chainlen
for l in words:
l = l.strip()
oldnames.append(l)
s = " " * chainlen + l
for n in range(0,len(l)):
self.mcd.add_key(s[n:n+chainlen], s[n+chainlen])
self.mcd.add_key(s[len(l):len(l)+chainlen], "\n")
def New(self):
"""
New name from the Markov chain
"""
prefix = " " * self.chainlen
name = ""
suffix = ""
while True:
suffix = self.mcd.get_suffix(prefix)
if suffix == "\n" or len(name) > 9:
break
else:
name = name + suffix
prefix = prefix[1:] + suffix
return name.capitalize()
for i in range(1):
word = (MName().New())
How do I make this execute an arbitrary number of times? How do I make it output to a text file?
You can make the code loop 400 times by using
f = open('file.txt', 'w')
# open the file before the loop to prevent opening the file multiple times
for i in range(400):
# Code that you want to run
print(i)
# write the output from the module in a text file
f.write(outputfrommodule)
# close text file
f.close()
I'm not familiar with the module so if you can figure out how to get the output you can just use the code above
I'm available for questioning if you need help with my answer
I'm trying to have the first function to open the file and the second function to print the contents of the file. Running into a few errors if someone could help me out the would be great!
global strings
def open_file():
file = askopenfile(parent=root,mode ='r', filetypes =[("All files", "*")])
if file is not None:
content = file.read()
strings = content.splitlines()
return strings
def run_file(some_content):
for i in some_content:
print(bytes(i,"ascii"))
time.sleep(1)
btn_upload = Button(root, text="UPLOAD",bg='#34495e', fg='white', command = lambda:open_file())
btn_upload.pack()
btn_run = Button(root, text="RUN",bg='#34495e', fg='white', command=lambda:run_file(strings))
btn_run.pack()
You'll need to put global strings inside the open_file() function (and indeed in any function that assigns to that name; reading from globals works without global).
strings = None
def open_file():
global strings
# ...
def run_file():
for i in strings:
# ...
However, in the name of testability etc., I'd avoid using global variables and maybe just encapsulate your state into a class.
My kivy application uses buttons, and these buttons correspond with json elements in a separate json file.
This would be button Eight
"Eight": {
"action": "Eight",
"delay": 1.55975283E9,
"seconds": 0,
"score": 0,
"delta": 1.55974682E9,
"grace_sec": 6000
}
When I press the button the score will add a value of 1 every time. However, when I add another button the score is reset to 0.
I'm really not sure what it is because at one point my code didn't do this. I must have changed something without noticing. I believe that the problem may have to do with kivy's store function but I am not sure.
I will include all code that I believe may be affecting the json file.
class MainApp(App):
def build(self): # build() returns an instance
self.store = JsonStore("streak.json") # file that stores the streaks:
Clock.schedule_interval(self.check_streak, 1/30.) # used to call functions dynamicaly
Clock.schedule_interval(self.score_gone, 1/30.)
Clock.schedule_interval(self.update_high, 1/30.)
return presentation
This function is longer but I'm only including the part that adds a score of 1.
def check_streak(self, dt):
for child in reversed(self.root.screen_two.ids.streak_zone.children):
name = child.id
with open("streak.json", "r") as read_file:
data = json.load(read_file)
for key in data.keys():
if key == name:
delay = data.get(key, {}).get('delay') # get value of nested key 'delay'
self.honey = data[key]['delta']
float(self.honey)
...
elif delay > time.time() > self.honey: # on time (green)
child.background_normal = ''
child.background_color = [0, 1, 0, .95]
child.unbind(on_press=self.early_click)
child.bind(on_press=self.add_score)
child.bind(on_press=self.display_streak)
child.bind(on_press=self.draw_streak)
child.unbind(on_press=self.late_click)
# add 1 to score and store in json file
def add_score(self, obj):
name = obj.id
with open("streak.json", "r") as file:
read = json.load(file)
for key in read.keys():
if key == name:
with open("streak.json", "r+") as f:
data = json.load(f)
data[key]['score']+=1
grace_sec = data.get(key, {}).get('grace_sec')
new_delay = time.time() + grace_sec
data[key]['delay'] = new_delay
seconds = data.get(key, {}).get('seconds')
new_delta = time.time() + seconds
data[key]['delta'] = new_delta
f.seek(0)
json.dump(data, f, indent=4)
f.truncate()
I'm including this because its an instance of the main app and is always being called on due to the Clock function but I don't think its the cause of the problem so you can ignore if thats the case.
# changes score to 0 and stores in json file
def score_gone(self, dt):
for child in self.root.screen_two.ids.streak_zone.children:
name = child.id
color = child.background_color
with open("streak.json", "r") as file:
read = json.load(file)
if color == [1, 0, 0, .95]: # red
if read[name]['score'] != 0: #stops slow down from Clock
with open("streak.json", "r+") as f: # fix score not reseting to 0
data = json.load(f)
data[name]['score'] = 0
f.seek(0)
json.dump(data, f, indent=4)
f.truncate()
elif read[name]['score'] == 0: #stops slow down from Clock
pass
This is the function that creates the streak from text input in a previous page.
# creates the Streak object
def create(self):
...
# store streak attributes inside "streak.json"
self.store.put(self.streak.action, action=self.streak.action,
delay=grace, seconds=total,
score=0, delta=self.count, grace_sec=grace_sec)
self.change_screen(self) # changes to screen that displays buttons
This function displays the buttons.
# display the names of the streaks in a list on PageTwo
def display_btn(self):
no_data = "You have no stored streaks!"
popup_2 = Popup(title="No Streaks!", content=Label(text=no_data),
size_hint=(None, None), size=(300, 100))
with open("streak.json", "r") as read_file:
data = json.load(read_file)
for value in data.values():
if value['delta'] is not None:
print(f"action={value['action']}, delta={value['delta']}, grace={value['delay']}")
streak_button = StreakButton(id=(value['action']), text=(value['action'] + " " + "[" + str(value['score']) + "]"),
color=(0,0,0,1), size=(400, 50),
size_hint=(None, None))
self.root.screen_two.ids.streak_zone.add_widget(streak_button)
...
All of the button widgets are deleted when leaving the page and display_btn is called when entering the page. What's weird to me is how the program remembers what the score value is before adding a new button even though the json file updates to the new score. If I were to add a score of 1 to the button Eight then close out of the program; The application would remember that the value was 1. So if I added a value of 2 and then added a new button the value of Eight's score would reset to 1 because that was its value before I closed the application.
EDIT
This is all of the code in create it is used to gather data from text input inside of a page. The math that your seeing is simply turning the input into seconds for a later function that compares the time (I'm not sure if this necessary)
def create(self):
obj = self.root.get_screen('one') # get info from ScreenOne
self.streak = Streak(obj.ids.action_entry.text, obj.ids.delay_entry.text,
obj.ids.day_entry.text, obj.ids.hour_entry.text,
obj.ids.minute_entry.text)
empty_error = "Make sure to fill out all boxes!" # not in use yet
popup = Popup(title="Not filled", content=Label(text=empty_error),
size_hint=(None, None), size=(300, 100))
# error handling and calculating total seconds
parsed = False
try:
total = ((int(self.streak.day) * 86400) + (int(self.streak.hour) * 3600) +
(int(self.streak.minute) * 60)) # convert into seconds
self.current_time = time.time()
self.count = self.current_time + total
grace = (int(self.streak.delay) * 60) + self.count # aka delay
grace_sec = (int(self.streak.delay) * 60) + total
parsed = True
# delete later just used to test
print("[seconds:", total, ']', "[action:", self.streak.action, ']',
"[grace:", grace, ']')
# store streak attributes inside "streak.json"
self.store.put(self.streak.action, action=self.streak.action,
delay=grace, seconds=total,
score=0, delta=self.count, grace_sec=grace_sec)
self.change_screen(self)
except ValueError as error:
popup.open()
create uses an instance of Streak
class Streak():
def __init__(self, action, delay, day, hour, minute, score=0, delta=0):
self.action = action
self.delay = delay
self.day = day
self.hour = hour
self.minute = minute
self.score = score
self.delta = delta
The JSON file being reset because self.store was populated in the build() method with the image before the add. Add self.store = JsonStore("streak.json") into create() method.
Snippets
def create(self):
self.store = JsonStore("streak.json")
json resets when you add new info you need to add the info before with the new one that what i think its causing the problem
So I've got a couple global variables: directory_name and file_list
They're defined at the top and then I give them values in main. I need their values in a function called checkDirectory(blocknum). If I print their values before I call the function, they're correct, but in the function they are empty. This is some of the code:
file_list = []
directory_name = ""
def checkDirectory(blocknum):
global directory_name
global file_list
directory = tokenize(open(directory_name + '/' + file_list[blocknum], 'r').read())
main():
try:
directory_name = sys.argv[1]
if not os.path.exists(directory_name):
print("This is not a working directory.")
return
except:
directory_name = os.getcwd()
files = os.listdir(directory_name)
file_list = sorted(files, key=lambda x: int((x.split("."))[1].strip()))
....
checkDirectory(26)
This is a basic 100 line script, and I can pass in the variables but I'll have to do that for three or four functions which will be recursive, so I'd rather not have to do it every time.
You are shadowing directory_name and file_list in your main function. Since those variables are not known in that scope, they get created locally. In order to operate on the global variables, you need to declare them global in your main() as well:
file_list = []
directory_name = ""
def checkDirectory(blocknum):
global directory_name
global file_list
directory = tokenize(open(directory_name + '/' + file_list[blocknum], 'r').read())
main():
global directory_name
global file_list
...
Please remember that, as mentioned in the comments, using globals is not good practice and can lead to bad code in the long run (in terms of unreadable/unmaintainable/buggy).
I wrote the below code in order to check for three files and whichever files exist, run a "scan" on the file (if a file does not exist, don't worry about it just run a "scan" on the available files) and produce the proper output file on those available files.
The program I'm working on includes the following code:
def InputScanAnswer():
scan_number = raw_input("Enter Scan Type number: ")
return scan_number
This function checks if these three files exist and if so, assign specific values to hashcolumn and to filepathNum
def chkifexists():
list = ['file1.csv', 'file2.csv', 'file3.csv']
for filename in list:
if os.path.isfile(filename):
if filename == "file1.csv":
hashcolumn = 7
filepathNum = 5
if filename == "file2.csv":
hashcolumn = 15
filepathNum = 5
if filename == "file3.csv":
hashcolumn = 1
filepathNum = 0
#print filename, hashcolumn, filepathNum
def ScanChoice(scan_number):
if scan_number == "1":
chkifexists()
onlinescan(filename, filename + "_Online_Scan_Results.csv", hashcolumn, filepathNum) #this is what is giving me errors...
elif scan_number == "2":
print "this is scan #2"
elif scan_number =="3":
print "this is scan #3"
else:
print "Oops! Invalid selection. Please try again."
def onlinescan(FileToScan, ResultsFile, hashcolumn, filepathNum):
# web scraping stuff is done in this function
The error that I run into is global name 'filename' is not defined.
I realize that the problem is I'm attempting to send local variables from chkifexists() to the onlinescan() parameters. I tried using
return filename
return hashcolumn
return filepathNum
at the end of the chkifexists() function but that was not working either. Is there anyway to do what I'm trying to do in the
onlinescan(filename, filename + "_Online_Scan_Results.csv", hashcolumn, filepathNum)
line without using global variables? I know they are discouraged and I'm hoping I can go about it another way. Also, does having hashcolumn and filepathNum parameters in onlinescan() have anything to do with this?
Inside chkifexists, you would return all three variables like so:
return (filename, hashcolumn, filepathNum)
You would retrieve these by calling the function like so:
(filename, hashcolumn, filepathNum) = chkifexists()
You now have them in your function scope without needing global variables!
Technically, you don't need the parenthesis, either. In fact, I'm not sure why I included them. But it works either way, so what the heck.