I want to have a new file created each time a button is pressed.
To make things easier I choose to use Time to make unique file names.
But for some reason this only creates the file once, and writes to it the next time:
import os
timestr = time.strftime("%H-%M-%S")
dpath = os.path.join(os.path.expanduser("~"), "Documents")
if not os.path.exists(dpath):
os.makedirs(dpath)
fpath = os.path.join(dpath, timestr + ".bat")
open(fpath, "w+").write("""netsh interface ipv4 set address name="Ethernet" static """ +
str(sf1) + " " + str(sf2) + " " + str(sf3))
Please do the following to solve your problem. Follow comments and feel free to ask questions.
from datetime import datetime
import time
def read_to_file_once(list_of_strings):
filename = "myfile" + datetime.today().strftime("%Y_%m_%d_%H_%M_%S") # get date and time now
with open(filename, mode="a") as f: # append mode "a" create file if it even doe not exist
for line in list_of_strings:
f.write(str(line)+"\n")
if __name__ == "__main__":
read_to_file_once([111, 1112, 3434])
time.sleep(2)
read_to_file_once([888, "ABC", 3434])
Related
I need to get date from file name in python code. I found many solutions, but from fixed name and date. But I dont know what the name of the file will be, date is changing. How to do that?
I have a code which is working for known file name (current date), file is called micro20230125.txt
import re
import os
from datetime import datetime
header = """#SANR0000013003;*;#CNR0010;*;#RINVAL-777.0;*;"""
current_timestamp = datetime.today().strftime('%Y%m%d')
input_file = "micro" + current_timestamp + ".txt"
output_file = os.path.splitext(input_file)[0] + ".zrxp"
with open(input_file, "r") as f:
first_line = f.readline().strip('\n')
text = re.search('(\d{6})', first_line).group(1)
text = header + "\n" + text + "\n"
with open(output_file, "w") as f:
f.write(text)
print(text)
`
but I dont need current date. I will get file with some random date, so how can I extract unknown date from file name? How to change this variable current_timestamp?
I tried to use regex but I messed something up
EDIT: DIFF CODE, SIMILAR PROBLEM:
I was dealing with this code and then realized: python doesnt know what those numbers in name represent, so why treat them like a date and complicate things? Those are just numbers. As a matter of fact, I need those numbers as long as full file name. So I came up with different code.
import re
import os
def get_numbers_from_filename(filename):
return re.search(r'\d+', filename).group(0) #returns only numbers
for filename in os.listdir("my path"):
print (get_numbers_from_filename(filename))
def get_numbers_from_filename(filename):
return re.search(r"(.)+", filename).group(0) #returns all name
for filename in os.listdir("my path"):
print(get_numbers_from_filename(filename))
file was: micro20230104.txt
and result is:
result
Now, I want to use that result, dont want to print it.
No matter how I get that returns me error.
import re
import os
def get_numbers_from_filename(filename):
return re.search(r"(.)+", filename).group(0)
for filename in os.listdir("my path"):
print(get_numbers_from_filename(filename))
m = get_numbers_from_filename(filename)
output_file = os.path.splitext(m)[0] + ".zrxp"
with open(m, "r") as f:
first_line = f.readline().strip('\n')
text = re.search('(\d{6})', first_line).group(1)
text = header + "\n" + text + "\n"
with open(output_file, "w") as f:
f.write(text)
print(text)
but it it says error
error:there is no such file
what to do? what am I doing wrong?
Well, in case all the files have the format 'micro[YearMonthDay].txt', you can try this solution:
import os
from datetime import datetime
header = """#SANR0000013003;*;#CNR0010;*;#RINVAL-777.0;*;"""
#Change the variable folder_path for your actual directory path.
folder_path = "\\path_files\\"
filenames = []
# Iterate directory
for path in os.listdir(folder_path):
# check if current path is a file
if os.path.isfile(os.path.join(folder_path, path)):
filenames.append(path)
dates = []
for filename in filenames:
# First solution:
filename = filename.replace('micro', '')
filename = filename.replace('.txt', '')
date = datetime.strptime(filename, "%Y%m%d")
# Second solution:
# date = datetime.strptime(filename, "micro%Y%m%d.txt")
dates.append(date)
for date in dates:
print(date.strftime("%Y/%m/%d"))
with open(f'.\\micro{date.strftime("%Y/%m/%d")}.txt', "r") as f:
first_line = f.readline().strip('\n')
text = re.search('(\d{6})', first_line).group(1)
text = header + "\n" + text + "\n"
with open(output_file, "w") as f:
f.write(text)
print(text)
Use the solution you prefer and comment the other one.
Testing:
Text files for test
Code
Result
I hope I could help! :D
I'm making a pdf 'date checker' in Python which tells me if every page of the pdf has tomorrows date at the top (for checking newspapers as part of my job).
So far so good until I attempted to put it all into a GUI, the buttons display the correct filename, but only open and check the last file in he list the buttons were generated from 'Files[i]'.
Can anybody figure out from my horrible nooby code why this is happening? please excuse the mess (I'm new) :)
Here is my ugly code :) I think the issue is either where I open the file using
'with open(files[i])' or 3rd line from the bottom where the buttons are created.
Any help would be greatly appreciated, thank you.
import os, glob
import fileinput
import tkinter as tk
import dateutil
import datetime
from dateutil.relativedelta import *
from dateutil.easter import *
from dateutil.parser import *
from dateutil.rrule import *
import PyPDF2
from PyPDF2 import PdfReader
from datetime import datetime, timedelta
from tkinter import *
folder_path = 'C:users/axlra/documents/datechecker'
for filename in glob.glob(os.path.join(folder_path, '*.pdf')):
with open(files[i], 'r') as f:
text = f.read()
print (files[i])
print (len(text))
def checknow():
tomorrow = (datetime.now() + timedelta(days=1)).strftime("%d-%m-%Y")
file = open(files[i], 'rb')
reader = PdfReader(files[i])
total = len(reader.pages)
for x in range(total+1):
if x > total: file.close()
page = reader.pages[0]
found = False
text = (page.extract_text())
parts = []
def visitor_body(text, cm, tm, fontDict, fontSize):
y = tm[5]
if y > 1600 and y < 10000:
parts.append(text)
page.extract_text(visitor_text=visitor_body)
text_body = "".join(parts)
#print(text_body)
word = text_body
word=word[22:-1]
#print(word)
prodate = parse(word)
str_date = prodate.strftime("%d-%m-%Y")
print(str_date)
print(files[i])
if tomorrow in str_date:
found = True
if found:
#print(x)
print("Tomorrow's date was found on page"+ " "+str(x))
else:
#print(x)
print("Tomorrow's date was NOT found on page"+ " "+str(x))
location = os.getcwd() # get present working directory location here
counter = 0 #keep a count of all files found
files = [] #list to store all pdf files found at location
for file in os.listdir(location):
try:
if file.endswith(".pdf"):
print ("pdf file found:\t", file)
files.append(str(file))
counter = counter
except Exception as e:
raise e
print ("No files found here!")
root = Tk()
btn = [] #creates list to store the buttons ins
for i in range(counter): #this just popultes a list as a replacement for the actual inputs for troubleshooting purposes
files.append(str(i))
for i in range(len(files)): #this says for *counter* in *however many elements there are in the list files*
#the below line creates a button and stores it in an array we can call later, it will print the value of it's own text by referencing itself from the list that the buttons are stored in
btn.append(Button(root, text=files[i], command=checknow))
btn[i].pack() #this packs the buttons
root.mainloop()
Based off the given solutions, this is the working code, the solution was to completely get rid of the 'i list' and just use file_path:
import os
import tkinter as tk
from tkinter import messagebox
import os, glob
import fileinput
import tkinter as tk
import dateutil
import datetime
from dateutil.relativedelta import *
from dateutil.easter import *
from dateutil.parser import *
from dateutil.rrule import *
import PyPDF2
from PyPDF2 import PdfReader
from datetime import datetime, timedelta
from tkinter import *
import re
location = os.getcwd()
counter = 0
files = []
for file in os.listdir(location):
try:
if file.endswith(".pdf"):
print ("pdf file found:\t", file)
files.append(str(file))
counter = counter
except Exception as e:
raise e
print ("No files found here!")
tomorrow = (datetime.now() + timedelta(days=-1)).strftime("%A,%B%e")
tomorrow = tomorrow.replace(" ", "")
tomorrow2 = (datetime.now() + timedelta(days=-1)).strftime("%d.%m.%Y")
tomorrow2 = tomorrow.replace(" ", "")
tomorrow3 = (datetime.now() + timedelta(days=-1)).strftime("%A%e%B%Y")
tomorrow3 = tomorrow.replace(" ", "")
tomorrow4 = (datetime.now() + timedelta(days=-1)).strftime("%A,%B%e")
tomorrow4 = tomorrow.replace(" ", "")
tomorrow5 = (datetime.now() + timedelta(days=-1)).strftime("%A,%e%B")
tomorrow5 = tomorrow.replace(" ", "")
def open_pdf(file_path):
file = open(file_path, 'rb')
reader = PdfReader(file)
total = len(reader.pages)
for x in range(total):
if x > x: file.close()
page = reader.pages[x]
text = (page.extract_text())
text = text.replace(" ", "")
#print(text)
substring = tomorrow
first_index = text.find(substring)
if first_index != -1:
second_index = text.find(substring, first_index + len(substring))
if second_index != -1:
print("Tomorrows date "+ tomorrow+ " appears twice on page"+ " "+str(x).format(substring))
else:
print("Tomorrows date "+ tomorrow+ " appears only once on page"+ " "+str(x)+" -".format(substring))
else:
print("Tomorrows date "+ tomorrow+ " does not appear on page"+ " "+str(x)+" ---".format(substring))
def create_buttons(directory):
for filename in os.listdir(directory):
if filename.endswith(".pdf"):
file_path = os.path.join(directory, filename)
button = tk.Button(root, text=filename, command=lambda f=file_path: open_pdf(f))
button.pack()
root = tk.Tk()
create_buttons(os.getcwd())
root.mainloop()
The basic answer is that at the end of for i in range(len(files)) the i does not get dereference like it does in some languages. A simple test to do is that this will give you an i of 2.
for i in range(3):
pass
print(i)
So when you call checknow() the referenced file would be the last file in files since your i doesn't change after the loop.
Something I've done in the past is create a class encompassing it so that each one holds to their own references. I did it without subclassing the tkinter class, but you could. A sample for an idea of what I did is
class FileButton:
def checknow(self):
file_name = self._file_name
#as an example of how you can reference the file_name.
#you can also do this by doing self._button.cget("text") and not have to store file_name
pass
def __init__(self, root, file_name):
self._root = root
self._file_name = file_name
self._button = tkinter.Button(root, text=file_name, command=self.checknow)
self._button.pack()
for i in range(len(files)):
btn.append(FileButton(root, files[i]))
I haven't tested this particular code, and my previous uses were more for labels and entries, but the principle of it was the same and I can confirm that using the callback in this manner worked. Also, if you don't need to reference the buttons anymore you don't have to append them to the btn list either.
I am making code which generates a new text file with today's date each time it is run. For exemple today's file name would be 2020-10-05. I would like to increment it so that if the program is run one or more times the same day it becomes 2020-10-05_1, _2 etc..
I have this code that I found from another question and i've tried tinkering with it but I'm still stuck. The problem is here they convert the file name to an int 1,2,3 and this way it works but this isn't the result I want.
def incrementfile():
todayday = datetime.datetime.today().date()
output_folder = "//10.2.30.61/c$/Qlikview_Tropal/Raport/"
highest_num = 0
for f in os.listdir(output_folder):
if os.path.isfile(os.path.join(output_folder, f)):
file_name = os.path.splitext(f)[0]
try:
file_num = int(file_name)
if file_num > highest_num:
highest_num = file_num
except ValueError:
print("The file name %s is not an integer. Skipping" % file_name)
output_file = os.path.join(output_folder, str(highest_num + 1) + f"{todayday}" + ".txt")
return output_file
How can I modify this code so that the output I get in the end is something like 2020-10-05_0, _1, _2 etc.. ?
Thanks !
I strongly recommend you to use pathlib instead of os.path.join. This is more convenient.
def incrementfile():
td = datetime.datetime.today().date()
path = pathlib.Path("/tmp") #set your output folder isntead of /tmp
inc = len(list(path.glob(f"{td}*")))+1
outfile = path/f"{td}_{inc}.txt"
return outfile
Not a direct answer to your question, but instead of using _1, _2 etc, you could use a full timestamp with date and current time, which would avoid duplication, EG:
from datetime import datetime
t = str(datetime.now()).replace(":", "-").replace(" ", "_")
print(t)
Example output:
2020-10-05_13-06-53.825870
I think this will work-
import os
import datetime
#assuming files will be .txt format
def incrementfile():
output_folder = "//10.2.30.61/c$/Qlikview_Tropal/Raport/"
files=os.listdir(output_folder)
current_name=datetime.date.today().strftime('%Y-%m-%d_0')
current_num=1
def nameChecker(name,files):
return True if name +'.txt' in files else False
while namChecker(current_name,files):
current_name+='_'+str(current_num)
current_num+=1
return current_name+'.txt'
So I have my main python script which I run and essentially pass three arguments that are -p, -e and -d to another python script. I have been using subprocess in order to this which I understand.
What I want to achieve is rather than using subprocess I want to import the second file 'generate_json.py', and be able to pass the three arguments to its main() function. How can I pass the three arguments like I have in my subprocess call?
My code for my main script is as follows:
import generate_json as gs
def get_json_location(username=os.getlogin()):
first = "/Users/"
last = "/Desktop/data-code/Testdata"
result = first + username + last
return result
Assuming that the script files do not have to be used individually, i.e: generate_json.py on its own from the command line.
I think a cleaner approach would be to wrap generate_json.py functions and put it into a class.
In this case I renamed generate_json.py to ConfigurationHandling.py
import os
import json
from functions import read_config
class ConfigurationHandler(object):
def __init__(self, new_parameter_file, new_export_data_file, new_export_date):
self._parameter_file = new_parameter_file
self._export_data_file = new_export_data_file
self._export_date = new_export_date
self._parsed_configuration = self.read_configuration()
self._perform_some_action1()
self._perform_some_action2()
def _read_configuration(self):
"""Uses lower level function `read_config` in function.py file to read configuration file"""
parsed_configuration = read_config(self.export_data_file)
return parsed_configuration
def _perform_some_action1(self):
pass
def _perform_some_action2(self):
# Logic code for parsing goes here.
pass
def get_config(self):
"""Returns configuration"""
return [self.parameter_file, self.parsed_configuration, self.export_date]
def json_work(self):
cfg = self.get_config()[0] # json location
data = self.get_config()[1] # export_agent_core_agent.yaml
date = self.get_config()[2] # synthetic data folder - YYYY-MM-DD
if not date:
date = ""
else:
date = date + "/"
json_location = cfg # json data path
json_database = data["config"]["database"]
json_collection = data["config"]["collection"]
json_path = "{0}/{1}{2}/{3}/{3}.json".format(json_location, date, json_database, json_collection)
json_base_name = json_database + "/" + json_collection + "/" + os.path.basename(json_path) # prints json filename
current_day = date
with open('dates/' + current_day + '.json', 'a') as file:
data = {}
if os.path.exists(json_path):
json_file_size = str(os.path.getsize(json_path)) # prints json file size
print("File Name:" " " + json_base_name + " " "Exists " + "\n")
print("File Size:" " " + json_file_size + " " "Bytes " "\n")
print("Writing to file")
# if json_path is not False:
data['File Size'] = int(json_file_size)
data['File Name'] = json_base_name
json.dump(data, file, sort_keys=True)
file.write('\n')
else:
print(json_base_name + " " "does not exist")
print("Writing to file")
data['File Name'] = json_base_name
data['File Size'] = None
json.dump(data, file, sort_keys=True)
file.write('\n')
file.close()
Then in main.py
from ConfigurationHandler import ConfigurationHandler
def main():
#Drive the program from here and add the functionality together.
#Routine to do some work here and get the required variables
parameter_file = "some_parameter"
export_data_file = "some_file.yaml"
new_export_date = "iso_8601_date_etc"
conf_handl = ConfigurationHandler(parameter_file, export_data_file, new_export_date)
configuration = conf_handl.get_config()
conf_handl.json_work()
if __name__ == '__main__':
main()
In the project, you should aim to have only one main function and split up the functionality accordingly.
It will be much easier to change parts of the program later on when everything is split out evenly.
So far i have got the following :
from genrate_jsonv2 import ConfigurationHandler
import os
import argparse
def get_json_location(username=os.getlogin()):
first = "/Users/"
last = "/Desktop/data-code/Testdata"
result = first + username + last
return result
def get_config():
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--export-date", action="store", required=True)
args = parser.parse_args()
return [args.export_date]
yml_directory = os.listdir('yaml')
yml_directory.remove('export_config.yaml')
data = get_config()[0]
def main():
for yml in yml_directory:
parameter_file = get_json_location
export_data_file = yml
new_export_date = data
conf_handl = ConfigurationHandler(parameter_file, export_data_file, new_export_date)
configuration = conf_handl.get_config()
conf_handl.json_work()
if __name__ == '__main__':
main()
The issue is , within export_data_file , i don't really want to be passing a file_path location , i rather have it loop through each file_name in the yml directory. When doing so i get an error saying ,'Error reading config file'
I'm working with *.cfg files. The file can be read in a text editor like gedit and has this format:
% some comments
VAR_1= 1
%
% More comments
ANOTHER_VAR= -8
%
% comments again
VAR_THE_COMEBACK= 10
I want to create multiple config files just changing VAR_1= 1....2...3.........10. I manage to import the *cfg file without any new import in python but I'm not getting a way to change just this parameter, saving the file and creating another one with another value for VAR_1.
my code until now is really simple:
import os
os.chdir('/home/leonardo/Desktop')
f = open('file.cfg','r') #if I replace r by w I erase the file ....
a = f.read()
print a.find('1')
a.replace('1','2') #I tried this but. ... :(
f.close()
Any tips ?
Thank you for the help !
Untested code, but you will get the idea:
with open('file.cfg', 'r') as f:
contents_by_line = f.readlines()
for var_index, line in enumerate(contents_by_line):
if line.startswith("VAR_"):
break
else:
raise RuntimeError("VAR_ not found in file")
for var_i, new_cfg_file in ((2,"file2.cfg"),
(3, "file3.cfg")): #add files as you want
with open(new_cfg_file, "w") as fout:
for i, line in enumerate(contents_by_line):
if i == var_index:
fout.write("VAR_1=%d\n" % var_i)
else:
fout.write(line)
Thank you guys for all the help. I changed my approach to the problem, since the lines would be all the 'same', I just created a new line and replaced with a function I found here in stack. I hope it will help someone someday.
This script will automate a series of CFD simulations for my final project at college. It creates a series of folders with some simulation conditions on the name, copies the mesh file to the folder created as well as the new config file, the last line will run the code but I need to work in the base simulation setup to run the script.
The code is just in preliminary fase, I'll change it to be more readable and to be easily modified.
thank you guys !
Any tip is welcome, I'm trying to improve my coding skill : )
the code :::
import fileinput
import os
import shutil
import subprocess
class stuff:
root_folder = '/home/leonardo/Desktop/testzone'
mini_mach = 0.3
maxi_mach = 1.3
number_steps = 3
increment = ((maxi_mach-mini_mach)/number_steps)
config_file = 'inv_NACA0012.cfg'
parameter_1 = 'MACH_NUMBER= 0.8'
parameter_2 = 'CONV_NUM_METHOD_ADJFLOW= JST'
init_pa = 'MACH_NUMBER= ' #use a space after '='
init_pa2 = 'CONV_NUM_METHOD_ADJFLOW= ' #use a space after '='
airfoil = 'NACA0012'
command1 = 'parallel_computation.py -f ' #use space before the last " ' "
command2 = '-n 2'
mesh_file = 'mesh_NACA0012_inv.su2'
class modify:
def replaceAll(self,files,searchExp,replaceExp):
for line in fileinput.input(files, inplace=1):
if searchExp in line:
line = line.replace(searchExp,replaceExp)
sys.stdout.write(line)
mod = modify()
stuff = stuff()
for i in xrange(stuff.number_steps):
mach_name = stuff.airfoil + '_mach_' + `float('%.2f'% stuff.mini_mach)`
folder_name = stuff.root_folder + '/' + mach_name
print 'creating ...' + folder_name
os.makedirs(folder_name)
file_father = stuff.root_folder + '/' + stuff.config_file
shutil.copy2(file_father,folder_name)
mesh_father = stuff.root_folder + '/' + stuff.mesh_file
shutil.copy2(mesh_father,folder_name)
os.chdir(folder_name)
pre_mod_file = mach_name + '.cfg'
os.renames(stuff.config_file,pre_mod_file)
new_parameter_1 = stuff.init_pa + `float('%.2f'% stuff.mini_mach)`
new_parameter_2 = stuff.init_pa2 + `float('%.2f'% stuff.mini_mach)`
mod.replaceAll(pre_mod_file,stuff.parameter_1,new_parameter_1)
mod.replaceAll(pre_mod_file,stuff.parameter_2,new_parameter_2)
stuff.mini_mach += stuff.increment
#subprocess.check_call(stuff.command + pre_mod_file + stuff.command2)