How to generate auto increment in a folder in python? - python

I am new to Python. Anyone help with how to generate auto-increment like B00001, B00002, B00003...... which can autosave the excel file name with a button in a specific folder.
I have tried with
global numXlsx
numXlsx = 1
wb.save(f'invoice/B{numXlsx}.xlsx')
numXlsx += 1
But when I click the button for few times with different data, it still keeps overwriting the B1.xlsx file. Anyone help with this :)

It sounds like the biggest problem you're having is that each button click is re-starting the execution of your python script, so using a global variable won't work since that doesn't persist across executions. In this case, I'd suggest using something like the pickle module to store and reload your counter value each time you execute your script. Using that module, your solution could look something like this:
import pickle
from pathlib import Path
# creates file if it doesn't exist
myfile = Path("save.p")
myfile.touch(exist_ok=True)
persisted = {}
with (open(myfile, "rb")) as f:
try:
persisted = pickle.load(f)
except EOFError:
print("file was empty, nothing to load")
# use get() to avoid KeyError if key doesn't exist
if persisted.get('counter') is None:
persisted['counter'] = 1
wb.save(f"invoice/B{persisted.get('counter')}.xlsx")
persisted['counter'] += 1
# save everything back into the same file to be used next execution
pickle.dump(persisted, open(myfile, "wb"))
BONUS: If you want the count to be padded with zeros in the filename, use persisted.get('counter'):05d in the curly brackets when saving the file. The 5 indicates you want the resulting value to be at least 5 characters long, so for example 2 would become 00002 and 111 would become 00111.

You can try using a global variable and incrementing it everytime.
Try with something like:
(inizialize it to 0)
global numXlsx # this is like your counter variable)
wb.save(f'folder/B{numXlsx}.xlsx')
numXlsx += 1 # Incrementing the variable so it does not overwrite the file as your code is doing
Have a nice day!

Related

How to use a variable dynamically from an imported module in python 3.8

I currently have the following file load.py which contains:
readText1 = "test1"
name1 = "test1"
readText1 = "test2"
name1 = "test2"
Please note that the number will change frequently. Sometimes there might be 2, sometimes 20 etc.
I need to do something with this data and then save it individually.
In my file I import load like so:
from do.load import *
#where do is a directory
I then create a variable to know how many items are in the file (which I know)
values = range(2)
I then attempt to loop and use each "variable by name" like so:
for x in values:
x = x + 1
textData = readText + x
nameSave = name + x
Notice I try to create a textData variable with the readText but this won't work since readText isn't actually a variable. It errors. This was my attempt but it's obviously not going to work. What I need to do is loop over each item in that file and then use it's individual variable data. How can I accomplish that?
This is a common anti-pattern that you are stepping into. Every time you think "I'll dynamically reference a variable to solve this problem" or "Variable number of variables!" think instead "Dictionary".
load.py can instead contain a dictionary:
load_dict = {'readText1':'test1','name1':'test1','readText2':'test2','name2':'test2'}
You can make that as big or small as you want.
Then in your other script
from do.load import *
#print out everything in the dictionary
for k,v in load_dict.items():
print(k,v)
#create a variable and assign a value from the dictionary, dynamically even
for x in range(2):
text_data = load_dict['readText' + x]
print(text_data)
x+=1
This should allow you to solve whatever you are trying to solve and won't cause you the pain you will find if you continue down your current path.
If you are trying to access the variables in the module you've imported, you can use dir.
loader.py
import load
values = dir(load) # All the values in load.py
# to get how many they are
num_vars = len([var for var in module_vars if not var.startswith("__")])
print(num_vars)
# to get their names
var_names = [var for var in module_vars if not var.startswith("__")]
print(var_names)
# to get their values
var_values = [globals()[f"module.{var}"] for var in var_names]
print(var_values)
However, it is unsafe as it may introduce security vulnerabilities to your code. It is also slower. You can use data structures as JNevil has said here, here
The file load.py will load only the last variable "readText1" and "name1".
To do what you are asking for, you have to open load.py file as a text file and then iterate over each line to get 2 variables ("readText1" and "name1") for each iteration.

Can I import a python file and change a variable and save it parmanently?

I created a file 'user.py' and I gave it a variable 'coin' = '100'
coin = 100
I created another file and import this code
import user
print(user.coin) # Output 100
user.coin = 50
This variable is not updated in the 'user.py' file. I can to change the value from 99 to 50.
I want the change in 'user.py' file
coin = 50
That's not how programming works. You for sure don't want to change the actual source code during execution.
What you are planing is more of a persistance topic. You could create a user that has a coins attribute and then store this somewhere - a file or a database for example. Then on the next execution you proceed from that state but your code should be unmodifiable except by yourself opening the file, writing stuff into it and saving again.
The variable 'coin' is assigned statically in user.py. You cannot change this in runtime. To change the assignation you would need to import the user.py as a textfile and edit accordingly.
See here.
assuming you know what you are doing, and there is no way to persist this data in json/yaml/xml do this:
import user
from inspect import getsource
import re
patterns = {
'coin':200
}
text =getsource(user)
for key,value in patterns.items():
finded = re.search(f'{key}.*',text).group()
text = text.replace(finded,f'{key} = {value}')
with open('user.py','w') as arq:
arq.write(text)

Python Script that is changes by execution

how can I write a script that it changes by execution?
For example, two a have script exist from two row:
list = [1, 2, 3, 4, 5]
sliced_list = list[0:1]
Executing it, 2nd row should be:
sliced_list = list[1:2]
and then,
sliced_list = list[2:3]
I want to modify variable "sliced_list" everytime I run this file.
Generally this is not something you should ever want to do, since it is likely to result in non-deterministic behavior, and in the event of a bug its possible to completely overwrite your script and lose data.
If you want to change the date your script is operating on you should store it persistently in some fashion. This could be in a separate file somewhere or in an environment variable.
But to do what your asking you would need to open the script, copy the contents, and modify the content as you desire like this:
with open("/path/to/script.py", 'r+') as script:
contents = script.read()
# ... some string logic here
# Point cursor to the beginning of the file
# If the original contents were longing than the new contents
# you'll have unwanted data at the end of the file.
script.seek(0)
script.write(contents)
You could save the start index into a file when you run the script. Then increment it and save it. Something like what is shown below.
import os
List=[1,2,3,4,5]
file=open('file.txt','r+')
start_index=int(file.read())
print(List[start_index:start_index+1])
file.close()
os.remove('file.txt')
file=open('file.txt','w')
file.write(str(start_index+1))
file.close()

Attempt to Load-Update-Resave Argument in a game

I am very new to programing and trying to learn by doing creating a text adventure game and reading Python documentation/blogs.
My issue is I'm attempting to save/load data in a text game to create some elements which carry over from game to game and are passed as arguments. Specifically with this example my goal recall, update and load an incrementing iteration each time the game is played past the intro. Specially my intention here is to import the saved march_iteration number, display it to the user as a default name suggestion, then iterate the iteration number and save the updated saved march_iteration number.
From my attempts at debugging this I seem to be updating the value and saving the updated value of 2 to the game.sav file correctly, so I believe my issues is either I'm failing to load the data properly or overwriting the saved value with the static one somehow. I've read as much documentation as I can find but from the articles I've read on saving and loading to json I cannot identify where my code is wrong.
Below is a small code snippet I wrote just to try and get the save/load working. Any insight would be greatly appreciated.
import json
def _save(dummy):
f = open("game.sav", 'w+')
json.dump(world_states, f)
f.close
def _continue(dummy):
f = open("game.sav", 'r+')
world_states = json.load(f)
f.close
world_states = {
"march_iteration" : 1
}
def _resume():
_continue("")
_resume()
print ("world_states['march_iteration']", world_states['march_iteration'])
current_iteration = world_states["march_iteration"]
def name_the_march(curent_iteration=world_states["march_iteration"]):
march_name = input("\nWhat is the name of your march? We suggest TrinMar#{}. >".format(current_iteration))
if len(march_name) == 0:
print("\nThe undifferentiated units shift nerviously, unnerved and confused, perhaps even angry.")
print("\nPlease give us a proper name executor. The march must not be nameless, that would be chaos.")
name_the_march()
else:
print("\nThank you Executor. The {} march begins its long journey.".format(march_name))
world_states['march_iteration'] = (world_states['march_iteration'] +1)
print ("world_states['march_iteration']", world_states['march_iteration'])
#Line above used only for debugging purposed
_save("")
name_the_march()
I seem to have found a solution which works for my purposes allowing me to load, update and resave. It isn't the most efficient but it works, the prints are just there to display the number being properly loaded and updated before being resaved.
Pre-requisite: This example assumes you've already created a file for this to open.
import json
#Initial data
iteration = 1
#Restore from previously saved from a file
with open('filelocation/filename.json') as f:
iteration = json.load(f)
print(iteration)
iteration = iteration + 1
print(iteration)
#save updated data
f = open("filename.json", 'w')
json.dump(iteration, f)
f.close

Python (2.7): Simple version checker

A preface: I'm a beginner at Python. I've tried guides for learning but I am awful at learning like that, so I'm trying to make a super simple update checker to get started that I slowly build upon. I've grabbed some code I found on here and modified it a bit, and alas, it doesn't work. It reads the local and external .txt files and prints their output (just to check that it's reading them correctly). It then fails at the if/elif/elif/else statement thing in some way, so some help there would be great!
It's currently telling me "NameError: global name 'i' is not defined" however I've gone through several different errors at this point and am really just looking for a solution, and from there I can work backwards. Thanks!
import Tkinter
import urllib
import time
print "test"
#previously self within the brackets
def updateCheck():
update = False
updateWindow = Tkinter.Toplevel()
updateWindow.title(string="Update Checker")
updateWindow.resizable(False, False)
#gets local version (file currently says "1.0")
localSource = open('version.txt', 'r')
localContents = localSource.read()
print "local version = " + localContents
#gets server version (file currently says "1.1")
serverSource = urllib.urlopen("http://raw.github.com/SamHH/ccr-version/master/version.txt")
serverContents = serverSource.read()
print "server version = " + serverContents
#checks for updates by comparing the above two -- doesn't work
if serverContents[i] > localContents[i]:
dataLabel = Tkinter.Label(updateWindow,text="\n\nThere is an update available.\n\n")
dataLabel.pack()
#need a way of opening a .url file in the same folder here, if possible
elif serverContents[i] < localContents[i]:
dataLabel = Tkinter.Label(updateWindow,text="\n\nYour installation appears to be broken.\n\n")
dataLabel.pack()
#need a way of opening a .url file in the same folder here, if possible, again
elif serverContents[i] == localContents[i]:
versionLabel = Tkinter.Label(updateWindow,text="\n\nYou are already running the most up to date version.\n\n")
versionLabel.pack()
#need a way of opening a .exe file in the same folder this time, if possible
else:
versionLabel = Tkinter.Label(updateWindow,text="\n\nYour install is corrupted. Doh!\n\n")
versionLabel.pack()
updateCheck()
if serverContents[i] > localContents[i]:
Notice that you never initialized i to a default value. It is looking up in your code to see if you had defined and set it outside the function (which you did not).
Put in a loop
for i in range(len(serverContents)):
You should also check that both lists are the same size or you will get an error when you try to index past the end.
Note that this assumes that the serverContents and localContents are both lists each of whose elements is a value to be compared. If the contents are text strings. then you will be looping over each character in the string. If that is what you want, you do not need to do it
f = '1.1a'
g = '1.1a'
f == g # shows True
f is g # shows False
This will mean that '1.1a' and '01.1a' will show different
However, this will allow for the case where version number is not totally numeric, which is a requirement if you use float(serverContents).
If both local and remove 'files' contain just a float, read one line from each and turn that into a float() so you can compare:
try:
localSource = open('version.txt', 'r')
localContents = float(localSource.readline())
except (IOError, ValueError):
versionLabel = Tkinter.Label(updateWindow,text="\n\nYour install is corrupted. Doh!\n\n")
versionLabel.pack()
return
serverSource = urllib.urlopen("http://raw.github.com/SamHH/ccr-version/master/version.txt")
serverContents = float(serverSource.readline())
You then use the localContents and serverContents names to compare:
if serverContents > localContents:
# etc.

Categories

Resources