Copy Contents of File Into a New File - python

I am trying to write a Python script that takes the contents of a text file, and copies it into a new file that the program creates itself.
This is the code I am testing at the moment:
from datetime import datetime
errorLogPath = datetime.strftime(datetime.now(), '%Y%m%d_%H:%M') + ".log"
with open("Report.log") as logFile:
with open(errorLogPath, 'w') as errorLog:
for line in logFile:
errorLog.write(line)
Currently the new file is created, but it is completely blank and has the wrong filename. The filename should be YYYYMMDD_HH:MM.log instead I am getting a filename which does not show the minutes and the file is empty.
EDIT: Removed an unnecessary if statement, but the code is still not functioning :\

The simplest way to copy the file in python without using shutil module is:
with open("Report.log") as logFile, open(errorLogPath, 'w') as errorLog:
errorlog.writelines(logFile)
To use the shutil module:
import shutil
shutil.copy("Report.log", errorLogPath)

The problem is in your path name, : is a reserved characters in windows, here is the whole list:
< (less than)
> (greater than)
: (colon)
" (double quote)
/ (forward slash)
\ (backslash)
| (vertical bar or pipe)
? (question mark)
(asterisk)
the colon is referred as:
A disk designator with a backslash, for example "C:\" or "d:\".
Therefore, the correct solution will be to change your errorLogPath to remove the : character.
Then, the best way to copy a file is yo use copy
from datetime import datetime
from shutil import copy
error_log_path = datetime.strftime(datetime.now(), '%Y%m%d_%H_%M') + ".log"
log_file_path = "Report.log"
copy(log_file_path, error_log_path)
Note:
You can open several files with a single with statement.
It is better not to use lower_case rather than camelCase for variable's name in python.

try this, this has worked for me:
from datetime import datetime
import csv
errorLogPath = datetime.strftime(datetime.now(), '%Y%m%d_%H:%M') + ".log"
ff = open(errorLogPath, 'w')
csvwriter = csv.writer(ff)
with open("Report.log","r") as logFile:
reader = csv.reader(logFile)
for line in reader:
if "ROW" in line:
csvwriter.writerow(line)
else:
continue
ff.close()

Related

How to create and write into a file correctly in Python

I am trying to create a file in a certain directory, and save the name of that file with today's date.
I am having some issue, where the file is created, but the title line that I want to write in, does not work.
from datetime import datetime
today = datetime.now().date().strftime('%Y-%m-%d')
g = open(path_prefix+today+'.csv', 'w+')
if os.stat(path_prefix+today+'.csv').st_size == 0: # this checks if file is empty
g = open(path_prefix+today+'.csv', 'w+')
g.write('Title\r\n')
path_prefix is just a path to the directory I am saving in /Users/name/Documents/folder/subfolder/
I am expecting a file 2019-08-22.csv to be saved in the directory given by path_prefix with a title as specified in the last line of the code above.
What I am getting is an empty file, and if I run the code again then the title is appended into the file.
As mentioned by #sampie777 I was not losing the file after writing to it, which is why the changes were not being saved when I opened the file. Adding close in an extra line solves the issue that I was having
from datetime import datetime
today = datetime.now().date().strftime('%Y-%m-%d')
g = open(path_prefix+today+'.csv', 'w+')
if os.stat(path_prefix+today+'.csv').st_size == 0: #this checks if file is empty
g = open(path_prefix+today+'.csv', 'w+')
g.write('Title\r\n')
g.close()
I am sure there are plenty of other ways to do this
You need to close the file before the content will be written to it. So call
g.close().
I can suggest to use:
with open(path_prefix+today+'.csv', 'w+') as g:
g.write('...')
This will automatically handle closing the file for you.
Also, why are you opening the file two times?
Tip: I see you are using path_prefix+today+'.csv' a lot. Create a variable for this, so you're code will be a lot easier to maintain.
Suggested refactor of the last lines:
output_file_name = path_prefix + today + '.csv' # I prefer "{}{}.csv".format(path_prefix, today) or "%s%s.csv" % (path_prefix, today)
is_output_file_empty = os.stat(output_file_name).st_size == 0
with open(output_file_name, 'a') as output_file:
if is_output_file_empty:
output_file.write('Title\r\n')
For more information, see this question: Correct way to write line to file?
and maybo also How to check whether a file is empty or not?
I haven't used Python in a while, but by doing a quick bit of research, this seems like it could work:
# - Load imports
import os
import os.path
from datetime import datetime
# - Get the date
dateToday = datetime.now().date()
# - Set the savePath / path_prefix
savePath = 'C:/Users/name/Documents/folder/subfolder/'
fileName = dateToday.strftime("%Y-%m-%d") # - Convert 'dateToday' to string
# - Join path and file name
completeName = os.path.join(savePath, fileName + ".csv")
# - Check for file
if (not path.exists(completeName)):
# - If it doesn't exist, write to it and then close
with (open(completeName, 'w+') as file):
file.write('Title\r\n')
else:
print("File already exists")

How can work output using python?

I made some script for modify text.
But I can't make result.
below is my script.
i just begin study python.
I think my script didn't work because f = open('find_c_volume_show.txt', 'w')
please help me.
import sys
from itertools import islice
def next_n_lines(file_opened, N):
return [x.strip() for x in islice(file_opened, N)]
field_line = 1
num = 0
N = 9
split_line = field_line / N
strings = ("Vserver", "Volume Name", "Used Size", "Available Size", "Volume Size", "Aggregate Name", "Space Saved by Storage Efficiency")
f = open('find_c_volume_show.txt', 'w')
for line in open("c_volume_show.txt"):
if any(s in line for s in strings):
field1,field2 = line.strip().split(':')
field_line += 1
f.write(field2 + '\n')
f.close()
f = open('find_c_volume_show.txt', 'w')
f.write("Vserver,Volume Name,Aggregate Name,Volume Size,Available Size,Used Size,Space Saved\n")
with open('find_c_volume_show.txt', 'w') as result:
while num < split_line:
num += 1
lines = next_n_lines(result, N)
f.write('{}'.format(','.join(lines)) +'\n' )
f.close()
below is my text file. text file has data multi data.
Vserver Name: FAS8040-ZZZZ
Volume Name: vol0
Aggregate Name: Node1_aggr0
Volume Size: 466.6GB
Available Size: 436.2GB
Filesystem Size: 466.6GB
Total User-Visible Size: 466.6GB
Used Size: 30.40GB
Used Percentage: 6%
Node name: FAS8040-ZZZZ
Space Saved by Storage Efficiency: 0B
Percentage Saved by Storage Efficiency: 0%
Space Saved by Deduplication: 0B
Space Saved by Compression: 0B
Percentage Space Saved by Compression: 0%
Total Physical Used Size: 22.37GB
I want result like below.
Vserver,Volume Name,Aggregate Name,Volume Size,Available Size,Used Size,Space Saved
FAS8040-ZZZZ,vol0,Node1_aggr0,466.6GB,435.7GB,30.92GB,0B
FAS8040-YYYY,vol0,Node2_aggr0,466.6GB,428.7GB,37.91GB,0B
FAS8040-XXXX,vol0,Node2_aggr0,466.6GB,428.7GB,37.91GB,0B
The problem is that each time you open file with open(filename,'w'), it gets erased. You can use "temporal" file with different name to store results of your first for loop, or I would suggest to aggregate content of each line to list, and then write it straight away.
Additionally, you have problems with your "split_line" value, it is always 0. I guess what you mean is len(strings).
Here is a code:
import sys
strings = ("Vserver", "Volume Name", "Used Size", "Available Size", "Volume Size", "Aggregate Name", "Space Saved by Storage Efficiency")
with open('find_c_volume_show.txt', 'w') as f:
f.write("Vserver,Volume Name,Aggregate Name,Volume Size,Available Size,Used Size,Space Saved,Snapshot,Total Used Size\n")
row = []
for line in open("c_volume_show.txt"):
if any(s in line for s in strings):
field1,field2 = line.strip().split(':')
row.append(field2)
print(row)
if len(row) == len(strings):
f.write('{}'.format(','.join(row)) +'\n' )
print(row)
row = []
The new-ish pathlib module (available in Python >= 3.4) is a much, much easier way for reading and writing files than the traditional open() function. It is also great for working with path-like objects (both in Windows and for other OSes).
from pathlib import Path
afile = Path(r'c:\temp\foo.bar') # absolute path to file
To read a file located at a path, you can just grab the text directly from the Path object!
contents = afile.read_text()
content_lines = contents.split('\n')
...and WRITE text directly!
data = '\n'.join(content_lines)
afile.write_text(data) # overwrites existing file
You can also use its open method rather than the open function:
with afile.open() as f:
dostuff(f)
The with statement is a context manager. It automatically "cleans up" by closing the file when you are done (no matter what happens- even if there is an error).
It's Paths - Paths all the way down
Here is more about the Path library copied from another of my answers.
To simplify: you can build up any path (directory and file path objects are treated exactly the same) as an object, which can be an absolute path object or a relative path object. You can use raw strings to make complex paths (i.e., r'string') and pathlib will be very forgiving. However, note that there are better ways to build up paths than raw strings (see further down).
Here are examples:
from pathlib import Path
Path(r'c:\temp\foo.bar') # absolute path
Path(r'c:/temp/foo.bar') # same absolute path
Path('foo.bar') # different path, RELATIVE to current directory
Path('foo.bar').resolve() # resolve converts to absolute path
Path('foo.bar').exists() # check to see if path exists
Note that if you're on Windows pathlib forgives you for using the "wrong slash" in the second example. See discussion at the end about why you should probably always use the forward slash.
Simple displaying of some useful paths- such as the current working directory and the user home- works like this:
# Current directory (relative):
cwd = Path() # or Path('.')
print(cwd)
# Current directory (absolute):
cwd = Path.cwd()
print(cwd)
# User home directory:
home = Path.home()
print(home)
# Something inside the current directory
file_path = Path('some_file.txt') # relative path; or
file_path = Path()/'some_file.txt' # also relative path
file_path = Path().resolve()/Path('some_file.txt') # absolute path
print(file_path)
To navigate down the file tree, you can do things like this. Note that the first object, home, is a Path and the rest are just strings:
afile = home/'Documents'/'Project Documentation'/'file.txt' # or
afile = home.join('Documents','Project Documentation','file.txt')
Check to see if it is a file or a directory (and exists) this way:
afile.is_dir()
afile.is_file()
Make a new, empty file without opening it like this (silently replaces any existing file):
afile.touch()
To make the file only if it doesn't exist, use exist_ok=False:
try:
afile.touch(exist_ok=False)
except FileExistsError:
# file exists
Make a new directory (under the current directory, Path()) like this:
Path().mkdir('new/dir') # get errors if Path()/`new` doesn't exist
Path().mkdir('new/dir', parents=True) # will make Path()/`new` if it doesn't exist
Path().mkdir('new/dir', exist_ok=True) # errors ignored if `dir` already exists
Get the file extension or filename of a path this way:
afile.suffix # empty string if no extension
afile.stem # note: works on directories too
Use name for the entire last part of the path (stem and extension if they are there):
afile.name # note: works on directories too
Rename a file using the with_name method (which returns the same path object but with a new filename):
new_file = afile.with_name('file_new.txt')
You can iterate through all the "stuff' in a directory like so using iterdir:
all_the_things = list(Path().iterdir()) # returns a list of Path objects
Sidebar: backslashes (\)
Be careful when using backslashes in a path string, especially ending a path with a backslash. As with any string, Python will read that terminating backslash as an escape character even in raw input mode. Observe:
>>> r'\'
File "<stdin>", line 1
r'\'
^
SyntaxError: EOL while scanning string literal
So this will give a pretty cryptic error message if you are not aware of this issue:
>>> Path(r'C:\')
File "<stdin>", line 1
Path(r'\')
^
SyntaxError: EOL while scanning string literal
The reason for this error is that \' is assumed to be a single quotation in the string. This works fine: '\'' (the second single quotation ends the string).
If you insist on using backslashes, be sure to use raw input mode or you will run into problems. For example, the '\t' character represents a tab. So when you do this (without raw input):
>>> Path('C:\temp')
You are putting a tab character into your path. This is perfectly legal and Python won't complain until you do something that causes Windows to try turning it into a real Windows path:
>>> Path('C:\temp').resolve()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: 'C:\temp'
This is also a very cryptic error if you do not know what is going on! Best to avoid the backslash characters altogether when messing about with paths.
It's work.
I change strings content.
Thank you so much.
strings = ("Vserver Name:", "Volume Name:", "Aggregate Name:", "Volume Size:", "Available Size:", " Used Size:", " Used Percentage:", "Node name:", "Space Saved by Storage Efficiency:")
with open('find_c_volume_show.txt', 'w') as f:
f.write("Vserver,Volume,Aggregate,Total,Avail,Used,UsedP,Node,Saved\n")
row = []
for line in open("c_volume_show.txt"):
if any(s in line for s in strings):
field1,field2 = line.strip().split(':')
row.append(field2.strip())
if len(row) == len(strings):
f.write('{}'.format(','.join(row)) +'\n' )
row = []
f.close()

Data disappearing from file when changing encoding python

So I've got this script I'm pretty satisfied with although it has one flaw. When changing the encoding it suddenly removes all the data from the file. No idea why. Got comments in the code for each line what it does.
Rename file --> Move File --> Change Encoding --> Exec SQL SP --> Move change back name + timestamp
import os
import shutil
import glob
import pyodbc
import os.path
import datetime
import codecs
#Defining function for SP
def SP():
cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=serv400;DATABASE=db;Trusted_Connection=yes')
cursor = cnxn.cursor()
query = "exec [PD_ABC_SP]"
cursor.execute(query)
cnxn.commit()
#Changing name, moving, importing and changing encoding for files in loop
destdir = '\\\\serv400\\f$\\BulkInsert\\Steve\\'
srcdir = '\\\\sesrv414\\Applications\\Prod\\IMP\\Phone\\'
inldir = '\\\\sesrv414\\Applications\\Prod\\IMP\\Phone\\Inlasta\\'
newfilename = 'Phone_Import_ABC.csv'
now = datetime.datetime.now() #Adding datetime for timestamp
for oldfilename in os.listdir(srcdir): #Looping through files in directory
if oldfilename.endswith(".csv"): #Changes filenames on files where name ends with csv
os.rename(srcdir + oldfilename, destdir + newfilename) #Changing old path + filename
codecs.open(destdir + newfilename, "w", encoding="utf-16") #switch encoding
SP() #Executing the function for the stored procedure
os.rename(destdir + newfilename, inldir + oldfilename + now.strftime("%Y%m%d"))
#Moving back the files including the timestamp
codecs.open(.., "w", ..) opens a file for writing and truncates any previous content. It does not convert the file for you. For that, you'll need to open the file using its current encoding, read its contents and then re-open it in write mode using the target encoding and write the contents back. Something like
contents = codecs.open(old_filename, "r", encoding="utf-8").read()
codecs.open(new_filename, "w", encoding="utf-16").write(contents)
should work.

How to create a file name with the current date & time in Python?

Here is a functional code (create file with success)
sys.stdout = open('filename1.xml', 'w')
Now I'm trying to name the file with the current date/time (I'm not an expert in Python)
filename1 = datetime.now().strftime("%Y%m%d-%H%M%S")
sys.stdout = open(filename1 + '.xml', 'w')
I want to write out a file name with the exact date and time, it is a xml file, that the program has already create, I just need to name the file. The above code is not working.
The error returned:
File "./fix.py", line 226, in <module>
filenames = datetime.now().strftime("%Y%m%d-%H%M%S")
AttributeError: 'module' object has no attribute 'now'
While not using datetime, this solves your problem (answers your question) of getting a string with the current time and date format you specify:
import time
timestr = time.strftime("%Y%m%d-%H%M%S")
print timestr
yields:
20120515-155045
so your filename could append or use this string.
Change this line
filename1 = datetime.now().strftime("%Y%m%d-%H%M%S")
To
filename1 = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
Note the extra datetime. Alternatively, change your
import datetime to from datetime import datetime
This one is much more human readable.
from datetime import datetime
datetime.now().strftime("%Y_%m_%d-%I_%M_%S_%p")
'2020_08_12-03_29_22_AM'
now is a class method in the class datetime in the module datetime. So you need
datetime.datetime.now()
Or you can use a different import
from datetime import datetime
Done this way allows you to use datetime.now as per the code in the question.
I'm surprised there is not some single formatter that returns a default (and safe) 'for appending in filename' - format of the time,
We could simply write FD.write('mybackup'+time.strftime('%(formatter here)') + 'ext'
"%x" instead of "%Y%m%d-%H%M%S"
Here's some that I needed to include the date-time stamp in the folder name for dumping files from a web scraper.
# import time and OS modules to use to build file folder name
import datetime
import time
import os
# Build string for directory to hold files
# Output Configuration
# drive_letter = Output device location (hard drive)
# folder_name = directory (folder) to receive and store PDF files
drive_letter = r'D:\\'
folder_name = r'downloaded-files'
folder_time = datetime.now().strftime("%Y-%m-%d_%I-%M-%S_%p")
folder_to_save_files = drive_letter + folder_name + folder_time
# IF no such folder exists, create one automatically
if not os.path.exists(folder_to_save_files):
os.mkdir(folder_to_save_files)
This prints in an easy to read format -
import datetime
time_now = datetime.datetime.now().strftime('%m_%d_%Y_%H_%M_%S')
print(time_now)
Output: 02_03_2021_22_44_50
import datetime
def print_time():
parser = datetime.datetime.now()
return parser.strftime("%d-%m-%Y %H:%M:%S")
print(print_time())
# Output>
# 03-02-2021 22:39:28

Add file name as last column of CSV file

I have a Python script which modifies a CSV file to add the filename as the last column:
import sys
import glob
for filename in glob.glob(sys.argv[1]):
file = open(filename)
data = [line.rstrip() + "," + filename for line in file]
file.close()
file = open(filename, "w")
file.write("\n".join(data))
file.close()
Unfortunately, it also adds the filename to the header (first) row of the file. I would like the string "ID" added to the header instead. Can anybody suggest how I could do this?
Have a look at the official csv module.
Here are a few minor notes on your current code:
It's a bad idea to use file as a variable name, since that shadows the built-in type.
You can close the file objects automatically by using the with syntax.
Don't you want to add an extra column in the header line, called something like Filename, rather than just omitting a column in the first row?
If your filenames have commas (or, less probably, newlines) in them, you'll need to make sure that the filename is quoted - just appending it won't do.
That last consideration would incline me to use the csv module instead, which will deal with the quoting and unquoting for you. For example, you could try something like the following code:
import glob
import csv
import sys
for filename in glob.glob(sys.argv[1]):
data = []
with open(filename) as finput:
for i, row in enumerate(csv.reader(finput)):
to_append = "Filename" if i == 0 else filename
data.append(row+[to_append])
with open(filename,'wb') as foutput:
writer = csv.writer(foutput)
for row in data:
writer.writerow(row)
That may quote the data slightly differently from your input file, so you might want to play with the quoting options for csv.reader and csv.writer described in the documentation for the csv module.
As a further point, you might have good reasons for taking a glob as a parameter rather than just the files on the command line, but it's a bit surprising - you'll have to call your script as ./whatever.py '*.csv' rather than just ./whatever.py *.csv. Instead, you could just do:
for filename in sys.argv[1:]:
... and let the shell expand your glob before the script knows anything about it.
One last thing - the current approach you're taking is slightly dangerous, in that if anything fails when writing back to the same filename, you'll lose data. The standard way of avoiding this is to instead write to a temporary file, and, if that was successful, rename the temporary file over the original. So, you might rewrite the whole thing as:
import csv
import sys
import tempfile
import shutil
for filename in sys.argv[1:]:
tmp = tempfile.NamedTemporaryFile(delete=False)
with open(filename) as finput:
with open(tmp.name,'wb') as ftmp:
writer = csv.writer(ftmp)
for i, row in enumerate(csv.reader(finput)):
to_append = "Filename" if i == 0 else filename
writer.writerow(row+[to_append])
shutil.move(tmp.name,filename)
You can try:
data = [file.readline().rstrip() + ",id"]
data += [line.rstrip() + "," + filename for line in file]
You can try changing your code, but using the csv module is recommended. This should give you the result you want:
import sys
import glob
import csv
filename = glob.glob(sys.argv[1])[0]
yourfile = csv.reader(open(filename, 'rw'))
csv_output=[]
for row in yourfile:
if len(csv_output) != 0: # skip the header
row.append(filename)
csv_output.append(row)
yourfile = csv.writer(open(filename,'w'),delimiter=',')
yourfile.writerows(csv_output)
Use the CSV module that comes with Python.
import csv
import sys
def process_file(filename):
# Read the contents of the file into a list of lines.
f = open(filename, 'r')
contents = f.readlines()
f.close()
# Use a CSV reader to parse the contents.
reader = csv.reader(contents)
# Open the output and create a CSV writer for it.
f = open(filename, 'wb')
writer = csv.writer(f)
# Process the header.
header = reader.next()
header.append('ID')
writer.writerow(header)
# Process each row of the body.
for row in reader:
row.append(filename)
writer.writerow(row)
# Close the file and we're done.
f.close()
# Run the function on all command-line arguments. Note that this does no
# checking for things such as file existence or permissions.
map(process_file, sys.argv[1:])
You can run this as follows:
blair#blair-eeepc:~$ python csv_add_filename.py file1.csv file2.csv
you can use fileinput to do in place editing
import sys
import glob
import fileinput
for filename in glob.glob(sys.argv[1]):
for line in fileinput.FileInput(filename,inplace=1) :
if fileinput.lineno()==1:
print line.rstrip() + " ID"
else
print line.rstrip() + "," + filename

Categories