简体   繁体   中英

Why am I getting a “NameError: name 'database' is not defined”, even if I am defining main?

When I try and run my code I am getting a Name Error:

Traceback (most recent call last):
  File "dna.py", line 24, in <module>
    main ()
  File "dna.py", line 15, in main
    STR_searcher()
  File "dna.py", line 19, in STR_searcher
    STR_dict = dict.fromkeys(range(1, len(database.fieldnames)))
NameError: name 'database' is not defined

When I put the helper function on top, the program worked but I am planning on using a few more functions so I want to put them at the bottom and define the first one as main. I also tried using if __name__ == "__main__": main() , but that didn't work either. So how can I have my other functions be put below main while ensuring that everything is defined?

from sys import argv, exit
import csv
from collections import OrderedDict

def main():
    if len(argv) != 3:
        print("Usage: python dna.py data.csv sequence.txt")
        exit(1)
    
with open(argv[1]) as csv_file: 
    database = csv.DictReader(csv_file)

    with open(argv[2]) as txt_file: 
        sequence = txt_file.read()
        STR_searcher()
                    
        
def STR_searcher():
    STR_dict = dict.fromkeys(range(1, len(database.fieldnames)))
    for i in range(len(STR_dict)):
        for j in range(len(sequence)):
            print("hello")        
            
main ()

It is because in the function scope of STR_searcher() the variable database is not defined. To give the variable to the function, defined it as: def STR_searcher(database): and call it from the main function like STR_searcher(database) .

This happens because your database variable is defined in the context of your main function and inside STR_searcher it's as if it doesn't exist. Consider moving this to a class, example:

def MyClass(object):
    def __init__(self):
        self.database =None
        self.sequence=None
    
    def main(self):
        if len(argv) != 3:
            print("Usage: python dna.py data.csv sequence.txt")
            exit(1)
            
        with open(argv[1]) as csv_file: 
            self.database = csv.DictReader(csv_file)
        
            with open(argv[2]) as txt_file: 
                self.sequence = txt_file.read()
                self.STR_searcher()
                        
            
    def STR_searcher(self):
        STR_dict = dict.fromkeys(range(1, len(self.database.fieldnames)))
        for i in range(len(STR_dict)):
            for j in range(len(self.sequence)):
                print("hello")    

You could then run it by doing:

Myclass().main()

You should pass the variables to the function

from collections import OrderedDict
from sys import argv, exit
import csv

def main():
    if len(argv) != 3:
        print("Usage: python dna.py data.csv sequence.txt")
        exit(1)

    with open(argv[1]) as csv_file: 
        database = csv.DictReader(csv_file)

    with open(argv[2]) as txt_file: 
        sequence = txt_file.read()
    
    STR_searcher(database, sequence)
        
def STR_searcher(database, sequence):
    STR_dict = dict.fromkeys(range(1, len(database.fieldnames)))
    for i in range(len(STR_dict)):
        for j in range(len(sequence)):
            print("hello")        
            
if __name__ == "__main__":
    main()

Or you can use global keyword however this is not a great way to do it.

from collections import OrderedDict
from sys import argv, exit
import csv

database = None
sequence = None

def main():
    global database
    global sequence

    if len(argv) != 3:
        print("Usage: python dna.py data.csv sequence.txt")
        exit(1)

    with open(argv[1]) as csv_file: 
        database = csv.DictReader(csv_file)

    with open(argv[2]) as txt_file: 
        sequence = txt_file.read()
    
    STR_searcher()
           
def STR_searcher():
    global database
    global sequence
    
    STR_dict = dict.fromkeys(range(1, len(database.fieldnames)))
    for i in range(len(STR_dict)):
        for j in range(len(sequence)):
            print("hello")        
            
if __name__ == "__main__":
    main()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM