Using variable as part of name of new file in python
<p>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:</p>

<pre><code>list = ["1.fasta", "2.fasta", "3.fasta"]
for file in list:
    contents = open(file, "r")
    for line in contents:
        if line[0] == "&gt;":
            new_file = open(file + "_chromosome.fasta", "w")
            new_file.write(line)
</code></pre>

<p>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:</p>

<blockquote>
  <p>python split_fasta.py *.fasta</p>
</blockquote>

<p>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:</p>

<blockquote>
  <p>python /home/bin/split_fasta.py /home/data/*.fasta</p>
</blockquote>

<p>This still creates the new files in the same directory as the fasta files. The issue here I'm sure is with this line:</p>

<pre><code>new_file = open(file + "_chromosome.fasta", "w")
</code></pre>

<p>Because if I change it to this:</p>

<pre><code>new_file = open("seq" + "_chromosome.fasta", "w")
</code></pre>

<p>It creates an output file in my current directory.</p>

<p>I hope this makes sense to some of you and that I can get some suggestions.</p>

<p>You are giving the full path of the old file, plus a new name. So basically, if <code>file == /home/data/something.fasta</code>, the output file will be <code>file +  "_chromosome.fasta"</code> which is <code>/home/data/something.fasta_chromosome.fasta</code></p>

<p>If you use <code>os.path.basename</code> on <code>file</code>, you will get the name of the file (i.e. in my example, <code>something.fasta</code>)</p>

<p>From @Adam Smith</p>

<blockquote>
  <p>You can use <code>os.path.splittext</code> to get rid of the <code>.fasta</code></p>

<pre><code>basename, _ = os.path.splitext(os.path.basename(file))
</code></pre>
</blockquote>

<hr>

<p>Getting back to the code example, I saw many things not recommended in Python. I'll go in details.</p>

<p>Avoid shadowing builtin names, such as <code>list</code>, <code>str</code>, <code>int</code>... It is not explicit and can lead to potential issues later.</p>

<p>When opening a file for reading or writing, you should use the <code>with</code> syntax. This is highly recommended since it takes care to close the file.</p>

<pre><code>with open(filename, "r") as f:
    data = f.read()
with open(new_filename, "w") as f:
    f.write(data)
</code></pre>

<p>If you have an empty line in your file, <code>line[0] == ...</code> will result in a <code>IndexError</code> exception. Use <code>line.startswith(...)</code> instead.</p>

<p>Final code :</p>

<pre><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("&gt;"):
                new_name = os.path.splitext(os.path.basename(file)) + "_chromosome.fasta"
                with open(new_name, "w") as output:
                    output.write(line)
</code></pre>

<p>Often, people come at me and say "<em>that's hugly</em>". Not really :). The levels of indentation makes clear what is which context.</p>

python fasta