I have a python list ['a','b','c'] that's generated inside a for loop. I would like to write each element of the list to a new file.
I have tried:
counter = 0
for i in python_list:
outfile = open('/outdirectory/%s.txt') % str(counter)
outfile.write(i)
outfile.close()
counter += 1
I get an error:
IOError: [Erno 2] No suchfile or directory.
How can I programmatically create and write files in a for loop?
You're not passing a mode to open, so it's trying to open in read mode.
outfile = open('/outdirectory/%s.txt' % str(counter), "w")
Try this:
out_directory = "/outdirectory"
if not os.path.exists(out_directory):
os.makedirs(out_directory)
for counter in range(0, len(python_list)):
file_path = os.path.join(out_directory, "%s.txt" % counter)
with open(file_path, "w") as outfile:
outfile.write(python_list[counter])
basically the message you get is because you try to open a file named /outdirectory/%s.txt. A following error as ErlVolton show is that you don't open your file in writing mode. additionaly you must check that you directory exist. if you use /outdirectory it means from the root of the file system.
Three pythonic additional:
- enumerate iterator which autocount the item in your list
- with statement autoclose your file.
- format can be a little clearer than % thing
so the code could be written in the following
for counter,i in enumerate(python_list):
with open('outdirectory/{}.txt'.format(counter),"w") as outfile:
outfile.write(i)
PS: next time show the full back trace
Some suggestions:
Use the with statement for handling the files
[docs].
Use the correct file open mode for writing [docs].
You can only create files in directories that actually exist. Your error message probably indicates that the call to open() fails, probably because the directory does not exist. Either you have a typo in there, or you need to create the directory first (e.g., as in this question).
Example:
l = ['a', 'b', 'c']
for i, data in enumerate(l):
fname = 'outdirectory/%d.txt' % i
with open(fname, 'w') as f:
f.write(data)
Related
I am new to programming and got an issue with writing bytes. Here is what I wrote:
file = open('filePath/input.train', 'wb')
for i in range(len(myList)):
file.write(bytes((myList[i]),'UTF-8'));
If I print 'i' here, it is 629.
The '.train' suffix is required by the project. In order to check it, I read it and write to a txt file:
file = open('filePath/input.train', 'rb')
content = file.read()
testFile = open('filePath/test.txt', 'wb')
testFile.write(content)
Now, the problem is, len(list) = 629 while I got 591 lines in test.txt file. It brought me problems later.
Why did this happen and how should I solve it?
first, when you open and write a file, need remember close the file after the write.like this.
file = open('filePath/input.train', 'wb')
for i in range(len(myList)):
file.write(bytes((myList[i]),'UTF-8'));
file.close()
second, python code not must has ";"
third, file is python's keyword, so don't use file be your variable name. you can use f or my_file or anyone, but don't use python's keyword.
fourth, python has a iterator, use iterator is better than your for i in range(len(xxx)).
all of this, your code can look like this.
f = open('filePath/input.train', 'wb')
for line in myList:
f.write(bytes(line, 'UTF-8'))
f.close()
I'm writing to a file in three functions and i'm trying not overwrite the file. I want every time i run the code i generate a new file
with open("atx.csv", 'w')as output:
writer = csv.writer(output)
If you want to write to different files each time you execute the script, you need to change the file names, otherwise they will be overwritten.
import os
import csv
filename = "atx"
i = 0
while os.path.exists(f"{filename}{i}.csv"):
i += 1
with open(f"{filename}{i}.csv", 'w') as output:
writer = csv.writer(output)
writer.writerow([1, 2, 3]) #or whatever you want to write in the file, this line is just an example
Here I use os.path.exists() to check if a file is already present on the disk, and increment the counter.
First time you run the script, you get axt0.csv, second time axt1.csv, and so on.
Replicate this for your three files.
EDIT
Also note that here I'm using formatted string literals which are available since python3.6. If you have an earlier version of python, use "{}{:d}.csv".format(filename, i) instead of f"{filename}{i}.csv"
EDIT bis after comments
If the same file is needed to be manipulated by more functionsduring the execution of the script, the easiest thing came to my mind is to open the writer outside the functions and pass it as an argument.
filename = "atx"
i = 0
while os.path.exists(f"{filename}{i}.csv"):
i += 1
with open(f"{filename}{i}.csv", 'w') as output:
writer = csv.writer(output)
foo(writer, ...) #put the arguments of your function instead of ...
bar(writer, ...)
etc(writer, ...)
This way each time you call one of the functions it writes to the same file, appending the output at the bottom of the file.
Of course there are other ways. You might check for the file name existence only in the first function you call, and in the others just open the file with the 'a' options, to append the output.
you can do something like this so that each file gets named something a little different and therefore will not be overwritten:
for v in ['1','2','3']:
with open("atx_{}.csv".format(v), 'w')as output:
writer = csv.writer(output)
You are using just one filename. When using the same value as a name atx.csv you will either overwritte it with w or append with a.
If you want new files to be created, just check first if the file is there.
import os
files = os.listdir()
files = [f for f in files if 'atx' in f]
num = str(len(files)) if len(files) > 0 else ''
filename = "atx{0}.csv".format(num)
with open(filename, 'w')as output:
writer = csv.writer(output)
Change with open("atx.csv", 'w') to with open("atx.csv", 'a')
https://www.guru99.com/reading-and-writing-files-in-python.html#2
I have a folder with csv formated documents with a .arw extension. Files are named as 1.arw, 2.arw, 3.arw ... etc.
I would like to write a code that reads all the files, checks and replaces the forwardslash / with a dash -. And finally creates new files with the replaced character.
The code I wrote as follows:
for i in range(1,6):
my_file=open("/path/"+str(i)+".arw", "r+")
str=my_file.read()
if "/" not in str:
print("There is no forwardslash")
else:
str_new = str.replace("/","-")
print(str_new)
f = open("/path/new"+str(i)+".arw", "w")
f.write(str_new)
my_file.close()
But I get an error saying:
'str' object is not callable.
How can I make it work for all the files in a folder? Apparently my for loop does not work.
The actual error is that you are replacing the built-in str with your own variable with the same name, then try to use the built-in str() after that.
Simply renaming the variable fixes the immediate problem, but you really want to refactor the code to avoid reading the entire file into memory.
import logging
import os
for i in range(1,6):
seen_slash = False
input_filename = "/path/"+str(i)+".arw"
output_filename = "/path/new"+str(i)+".arw"
with open(input_filename, "r+") as input, open(output_filename, "w") as output:
for line in input:
if not seen_slash and "/" in line:
seen_slash = True
line_new = line.replace("/","-")
print(line_new.rstrip('\n')) # don't duplicate newline
output.write(line_new)
if not seen_slash:
logging.warn("{0}: No slash found".format(input_filename))
os.unlink(output_filename)
Using logging instead of print for error messages helps because you keep standard output (the print output) separate from the diagnostics (the logging output). Notice also how the diagnostic message includes the name of the file we found the problem in.
Going back and deleting the output filename when you have examined the entire input file and not found any slashes is a mild wart, but should typically be more efficient.
This is how I would do it:
for i in range(1,6):
with open((str(i)+'.arw'), 'r') as f:
data = f.readlines()
for element in data:
element.replace('/', '-')
f.close()
with open((str(i)+'.arw'), 'w') as f:
for element in data:
f.write(element)
f.close()
this is assuming from your post that you know that you have 6 files
if you don't know how many files you have you can use the OS module to find the files in the directory.
I'm new to python and trying to create a csv file from a list of files within a folder. Essentially, the code is supposed to write rows based on the files in a folder by parsing the file name to isolate the unique identifier (which here is the name of a city), then writing that identifier to a column, followed by the original file name/file path to the attachment. This bit of code writes the headers, "City" and "Attachment", then stops and returns the error statement, that no PDFs are in the folder (there are, in fact, 100 PDF files in the folder).
Here is the code that I'm having some trouble editing:
attachments_folder = "H:/Attachments"
attachments_table = attachments_folder + "\\" + "attachments_Table.csv"
for f in os.listdir(attachments_folder):
file_name, file_ext = os.path.splitext(f)
f_file, f_city = file_name.split('_')
writer = csv.writer(open(attachments_table, "wb"), delimiter=",")
writer.writerow(["City", "Attachment"])
if str(f).find(".pdf") > -1:
writer.writerow([f_city, f])
else:
print "Error: no PDF's found"
I apologize in advance that this is likely a clunky and/or yucky bit of code. I was curious if I needed to break out the two things going on here (parsing the file name, then write lines to the csv rows), but I got syntax errors with this reformatted version:
for f in os.listdir(attachments_folder):
file_name, file_ext = os.path.splitext(f)
f_file, f_city = file_name.split('_')
writer = csv.writer(open(attachments_table, "wb"), delimiter=",")
writer.writerow(["City", "Attachment"])
for f in os.listdir(attachments_folder):
writer.writerow(["City", "Attachment"])
if str(f).find(".pdf") > -1:
writer.writerow([f_city, f])
else:
print "Error: no PDF's found"
Any guidance on what I'm missing here would be much appreciated! Thanks!
There are a couple of issues going on here:
Most importantly, you're overwriting the file in each step of the loop, thereby deleting whatever may have been written in prior steps.
Secondly, and likely adding to the confusion, your warning isn't telling the truth. One or more PDFs may have been found.
I fixed the first issue by opening the file only once, before the loop. I fixed the second issue by modifying the existing warning and adding another positive status when a PDF is found. Here's a working rewrite of your program (in Python 3):
# In Python 3, newline='' prevents extra blank rows. You don't need this in Python 2.
# You can also leave 'wb' as the file mode in Python 2.
with open(attachments_table, 'w', newline='') as output:
writer = csv.writer(output, delimiter=",")
writer.writerow(['City', 'Attachment'])
for f in os.listdir(attachments_folder):
file_name, file_ext = os.path.splitext(f)
f_file, f_city = file_name.split('_')
if str(f).find('.pdf') > -1:
print('The current file is a PDF.')
writer.writerow([f_city, f])
else:
print('The current file is not a PDF.')
I'm fairly new to python and I'm having an issue with my python script (split_fasta.py). Here is an example of my issue:
list = ["1.fasta", "2.fasta", "3.fasta"]
for file in list:
contents = open(file, "r")
for line in contents:
if line[0] == ">":
new_file = open(file + "_chromosome.fasta", "w")
new_file.write(line)
I've left the bottom part of the program out because it's not needed. My issue is that when I run this program in the same direcoty as my fasta123 files, it works great:
python split_fasta.py *.fasta
But if I'm in a different directory and I want the program to output the new files (eg. 1.fasta_chromsome.fasta) to my current directory...it doesn't:
python /home/bin/split_fasta.py /home/data/*.fasta
This still creates the new files in the same directory as the fasta files. The issue here I'm sure is with this line:
new_file = open(file + "_chromosome.fasta", "w")
Because if I change it to this:
new_file = open("seq" + "_chromosome.fasta", "w")
It creates an output file in my current directory.
I hope this makes sense to some of you and that I can get some suggestions.
You are giving the full path of the old file, plus a new name. So basically, if file == /home/data/something.fasta, the output file will be file + "_chromosome.fasta" which is /home/data/something.fasta_chromosome.fasta
If you use os.path.basename on file, you will get the name of the file (i.e. in my example, something.fasta)
From #Adam Smith
You can use os.path.splitext to get rid of the .fasta
basename, _ = os.path.splitext(os.path.basename(file))
Getting back to the code example, I saw many things not recommended in Python. I'll go in details.
Avoid shadowing builtin names, such as list, str, int... It is not explicit and can lead to potential issues later.
When opening a file for reading or writing, you should use the with syntax. This is highly recommended since it takes care to close the file.
with open(filename, "r") as f:
data = f.read()
with open(new_filename, "w") as f:
f.write(data)
If you have an empty line in your file, line[0] == ... will result in a IndexError exception. Use line.startswith(...) instead.
Final code :
files = ["1.fasta", "2.fasta", "3.fasta"]
for file in files:
with open(file, "r") as input:
for line in input:
if line.startswith(">"):
new_name = os.path.splitext(os.path.basename(file)) + "_chromosome.fasta"
with open(new_name, "w") as output:
output.write(line)
Often, people come at me and say "that's hugly". Not really :). The levels of indentation makes clear what is which context.