#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Posts
    19
    Rep Power
    0

    List is going out of scope


    I have a function in my code that is within another function that reads in data from a file into a list. The list that stores the file data immediately goes out of scope once that function is finished. I need my file data to always be available to the entire program.

    The code looks something like this:

    Code:
    my_file = []
    
    def first_function():
      # Some code here
    
      def inner_function():
        with open('mydoc.txt', 'r') as handle:
          my_file = handle.read().splitlines()
    
    def outer_function():
      for line in my_file: print line
    I get no output when I try to print the list outside of the inner_function. I've tried adding a "return my_file" to inner_function, but I still can't get the list to keep it's data. How do I force the list my_file to retain the file data?
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2009
    Posts
    474
    Rep Power
    33
    Why do you need a separate function for two lines of code and why is it nested? In any case, readlines will work better and a return will save the list.
    Code:
    def inner():
        with open('mydoc.txt', 'r') as fp:
            list_of_records = fp.readlines()
        return list_of_records

    Comments on this post

    • cspctec agrees
    Last edited by dwblas; May 28th, 2013 at 01:50 PM.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2013
    Posts
    19
    Rep Power
    0
    Originally Posted by dwblas
    I think it is probably the "with" statement scope and not the function (and why do you need a separate function for a one line statement?) that causes the list to be garbage collected. In any case, readlines will work better.
    Code:
    list_of_records = open('mydoc.txt', 'r').readlines()
    Thank you dwblas. It looks like your method works. I also found another way. If you declare a global list then append everything to that global list after reading in the file data, the global list will keep it's data for all functions to see.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2009
    Posts
    474
    Rep Power
    33
    That is considered bad practice. The function should not be nested, but should be a separate function and you should return the list to keep it from being garbage collected. See the modified post above.
  8. #5
  9. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,837
    Rep Power
    480
    When you assign data to a variable within a function it becomes local to that function. However, you can tell python otherwise with global or nonlocal statement.

    I believe this will work:
    Code:
      def inner_function():
        gobal my_file
        with open('mydoc.txt', 'r') as handle:
          my_file = handle.read().splitlines()
    Or maybe you need to return values from a function and pass values to a function.
    Code:
    def first_function():
      # Some code here
    
      def inner_function():
        with open('mydoc.txt', 'r') as handle:
          my_file = handle.read().splitlines()
        return my_file
    
      # ...
      my_file = inner_function()
      # ...
      return my_file
    
    
    def outer_function(LINES):
      for line in LINES: print line
    
    outer_function(first_function())
    nonlocal scope is another possibility in recent python versions. Someone else can explain which versions and what it does---or you could look up nonlocal at www.python.org .

    You want to read a file and keep the data around. I'd use class and object. Reading the file can be lazy, a good approach if you won't necessarily need the data, or in this case actively load the file into memory on reading it.
    Code:
    import sys
    
    class LinesOfFile(list):
    
        def __init__(self, fileName):
            with open(fileName) as inf:
                if '2' < sys.version[0]:
                    super().__init__(inf)
                else:
                    list.__init__(self, inf) # or however super is used in python 2.7
            self.fileName = fileName
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo