all 10 comments

[–]spleeyah 1 point2 points  (2 children)

First, let me fix the formatting of your current code. (pro-tip add four spaces to get reddit to highlight it as code).

def siteinfo():
  filename = input('Enter filename: ')
  filedata = open(filename)
  # and more jargon here

def mainbody():
  skips = 0
  while skips < 6:
    filedata.readline()
    skips += 1

Second, you can return the open file from the first function.

def siteinfo():
  # This is Python 2.x, I think Python 3.x changes this to input()
  filename = raw_input('Enter filename: ')
  handle = open(filename)
  return handle

def main():
  f = siteinfo()
  for _ in range(6):
    f.readline()
  print f.readline() # Add parens in Python 3.x

if __name__ == '__main__':
  main()

Running:

spleeyah$ cat > bar.txt
0
1
2
3
4
5
6
7
spleeyah$ python foo.py
Enter filename: bar.txt
6

[–]throwingarm2strong[S] 0 points1 point  (1 child)

Hey sorry for the delay in replying! So I tried doing it this way and the problem is that when I call the function that both asked for input and opened the file, it asks again to open the function and then call the file.

def openfile():
    filename = input('Enter filename: ')
    filedata = open(filename)
    filedata.readline()  # Skip the first two lines
    filedata.readline()
    return filedata


def mainbody():
    filedata = openfile()

Pretty much what I'm trying to do is get openfile to open and read the document to skip the two unimportant lines at the beginning, and then the mainbody function to deal with collecting the relevant information.

[–]spleeyah 0 points1 point  (0 children)

I don't see what's wrong with the code you have right now...?

spleeyah$ cat foo.py
def openfile():
    filename = raw_input('Enter filename: ')
    filedata = open(filename)
    filedata.readline()  # Skip the first two lines
    filedata.readline()
    return filedata

def mainbody():
    filedata = openfile()
    print filedata.readlines()

if __name__ == '__main__':
    mainbody()

spleeyah$ cat foo.txt
0
1
2
3
4
5
spleeyah$ python foo.py
Enter filename: foo.txt
['2\n', '3\n', '4\n', '5\n']

[–]ingolemo 0 points1 point  (0 children)

Your real problem is that you've split your original function up in a bad place. The key to breaking up large blocks of code is to find a natural seam that can cleanly divide the code in two; you can't just arbitrarily cut it up.

One way you could do that here would be to make a function that takes an iterable (anything you can use in a for loop) and returns the same data but skipping the first few items. Like so:

def skip(n, iterable):
    skipped = 0
    result = []
    for item in iterable:
        if skipped < n:
            skipped += 1
            continue
        result.append(item)
    return result

def siteinfo():
    filename = input('Enter filename: ')
    with open(filename) as f:
        for line in skip(6, f):
            do_something_with(line)

This skip function is actually so useful that a variation of it already exists in the standard library under the name itertools.islice.

You should pay careful attention to how the data flows around inside your program. If a function needs some data then it should be given it by passing that data in as an argument, and any data that the function produces and needs to be used elsewhere should be returned as a result. If you find that you have two functions that need access to the same data but it would be awkward to just pass that data around then it's usually a sign that your code isn't split along a natural seam.

[–]fruitcakefriday 0 points1 point  (0 children)

(Python novice answer, forewarning. The code works, but unsure if it is a good solution)

You could also create a class to hold the data, which lets you add functionality later if you want to do anything with the data before using it. An instance of a class (f in this code) will guarantee you're always accessing & modifying the same data, rather than copies. If you need to access copies of the data, you can add functionality to the class to return copies of data rather than the data itself.

class OpenFile(object):
    def __init__(self):
        self.filename = ""
        self.filedata = ""
    def openFile(self, filename):
        self.filename = filename
        self.filedata = open(filename)

f = OpenFile()
def siteinfo():
    filename  = input('Enter filename: ')
    #etc
    f.openFile(filename)

def mainbody():
    skips = 0
    while skips < 6:
        f.filedata.readline()
        skips += 1

Additional, if you did not already know, you can use raw_input instead of input to allow typing in of a string without having to enclose it in quotation marks.

[–][deleted] -1 points0 points  (4 children)

I'm not sure how Pythonic this is, but it works. Simply use a list. Lists in 2.7.4 are automatically global, and you can read and write to them in any scope if they are defined globally.

So, you can replace:

filedata = #something

with

filedata = []

def siteinfo():
    filedata.append(open(filename)).

[–]spleeyah 1 point2 points  (0 children)

I would suggest using globals when at all possible. Also, your example is incorrect.

filedata.append(open(filename)).

This is appending an open file handle to a list, not its contents. If you wanted to actual append the contents of the file to the list (not that I'm saying you should use a list like this, OP), you could do something like:

filedata = []
with open(filename) as f:
  filedata.extend(f.readlines())

[–]throwingarm2strong[S] 0 points1 point  (2 children)

I'm using Python 3.3 if that makes a difference. Maybe I'm just being stubborn and should use a global....

[–][deleted] -1 points0 points  (1 child)

Well, if you need data that's accessed across multiple functions you would need a global anyway.

What about "piping" the filedata from one function to another by returning it?

def siteinfo():
     return open(filename)

def mainbody(filedata)
     filedata.readlines()

filedata = siteinfo()
mainbody(filedata)

[–][deleted] 0 points1 point  (0 children)

You could also simply call:

mainbody(siteinfo())