0

For my class I have to write code that will receive a pathname and then display the file contents if its a file or display each file and its contents if a directory is the pathname.

I wrote the following code, which works fine when I test it with my own local directory. But when I run the checks on my class portal it returns an error "No such file or directory".

Can anyone help me see what's wrong with my code?

import os

def openFyle(filename):
    openFile = open(filename)
    return openFile.read()

def displayFiles(filename):
    if os.path.isdir(filename):
        os.chdir(filename)
        print("Directory name:", os.getcwd())
        dirLyst = os.listdir(filename)
        for file in dirLyst:
            if os.path.isfile(file):
                return print("File name:", file, openFyle(file))
            elif os.path.exists(file) and os.path.isdir(file):
                    os.chdir(file)
                    displayFiles(os.getcwd())
    else:
        print("File name:", filename, openFyle(filename))
        
def main():
    #while True:
    filename = input("Enter a pathname: ")
    displayFiles(filename)


if __name__ == "__main__":
    main()
  • The directory you are passing it does not exist on the class portal. – Alan Kavanagh Dec 30 '20 at 03:00
  • 1
    Use `os.getcwd()` to print out the directory that the script will be running in and then use a relative path from that location, or else find the absolute path of the directory you are trying to access and pass in that. – Alan Kavanagh Dec 30 '20 at 03:02
  • Thanks. But I'm not passing it any directory (am I?). I think the portal runs automated tests that pass it path names. –  Dec 30 '20 at 03:02
  • `return` stops your loop, but why are you using `os.getcwd()` in your recursion? – OneCricketeer Dec 30 '20 at 03:03
  • `filename = input("Enter a pathname: ")` this is reading in a path name – Alan Kavanagh Dec 30 '20 at 03:03
  • It isn't even clear if this is a bug in the code itself, or just you misreading the directions/requirements. If you ask on SO, make sure it's clear – user202729 Dec 30 '20 at 03:04
  • @OneCricketeer To move down to subdirectory and repeat process. –  Dec 30 '20 at 03:06
  • 1
    There are multiple branches and only one returns. Why does the outer else not return? - There is discrepancy between the branches in the displayFiles method – Alan Kavanagh Dec 30 '20 at 03:07
  • Thanks for your input. I ask on Substack because I always get almost immediate feedback! I will look into relative path thing you mentioned. –  Dec 30 '20 at 03:07
  • @AK47 One return for each element that is a file in the list of elements in the directory. –  Dec 30 '20 at 03:08
  • 1
    As soon as return is called, it will stop processing the other files - you might want to remove that? The problem with automated tests is that you need to read the requirement really carefully - are they asking for multiple files to be output to the screen? – Alan Kavanagh Dec 30 '20 at 03:10
  • 1
    Well, you don't need `os.chdir`, so `os.getcwd()` is also not needed within the function itself. You should be using `displayFiles(file)` to enter a subdirectory. You might also want to look at the `os.walk` or `glob` functions – OneCricketeer Dec 30 '20 at 03:11
  • Have you tested your code locally with a directory that has multiple files? – Alan Kavanagh Dec 30 '20 at 03:12
  • @AK47 Yes, sorry, I have fiddled with the code so much the last two hours that I forget what I changed for class portal vs what I had for my Jupyter notebook. You're right that return wasn't needed. I added it for a test in class portal. It works fine on my local files and directories. –  Dec 30 '20 at 03:16
  • @OneCricketeer Thanks for pointing out unnecessary bits. I'm not very familiar with os module and will look into what you mentioned more. I had to read through it earlier to get the isfile method. –  Dec 30 '20 at 03:18
  • 2
    Check this out: https://stackoverflow.com/a/55193831/4889267 – Alan Kavanagh Dec 30 '20 at 03:22
  • @AK47 Wow, thanks! I have never heard of glob so I don't think I'm expected to solve the problem with this. (We just had case study with os module in this chapter.) But this is a cool way to solve the problem and I'll make a note of it for future use. –  Dec 30 '20 at 03:26
  • @OneCricketeer when I remove os.chdir(file) and just have displayFile(file) in the body of the elif, my function returns an error when hits a subdirectory. But with those lines it behaves the way I want. –  Dec 30 '20 at 03:39

4 Answers4

0

What I would guess is, one of the tests they're using on your function is to send an invalid path. In your function, you only cover two cases: either its a path or its a file and you print out the file name with its contents. What if you cant find that file? That else should be an elif that does the os.path.isfile, and then an else in case its an invalid path.

This should fix it.

def displayFiles(filename):
    if os.path.isdir(filename):
        os.chdir(filename)
        print("Directory name:", os.getcwd())
        dirLyst = os.listdir(filename)
        for file in dirLyst:
            if os.path.isfile(file):
                return print("File name:", file, openFyle(file))
            elif os.path.exists(file) and os.path.isdir(file):
                    os.chdir(file)
                    displayFiles(os.getcwd())
    elif os.path.isfile(filename):
        print("File name:", filename, openFyle(filename))
    else:
        print("Invalid input")
sleao
  • 21
  • 4
0

Using the os module:

import os

def print_all_file_contents(directory):
    for root, dirs, files in os.walk(directory):
        for file in files:
            print(open(os.path.join(root, file)).read())

if __name__ == "__main__":
    print_all_file_contents(input("Enter a directory:"))
Alan Kavanagh
  • 9,425
  • 7
  • 41
  • 65
  • Awesome how concise this is! It works on my local files, but I'll need to tinker with it to understand the syntax better and test it on my class portal tomorrow. –  Dec 30 '20 at 03:53
  • Updated it slightly. Take the latest version – Alan Kavanagh Dec 30 '20 at 04:08
  • @AfterVirtue Tinker what? Just read the documentation. Python is very well-documented. – user202729 Dec 30 '20 at 08:02
  • @user202729 For instance doing stuff like this just helps me understand what the syntax is doing (sorry, don't know how to make formatting work in comments, but you may get the gist): `def display_files(path): for x, y, z in os.walk(path): print("This is root?", x) print("This is dir?", y)print("These are files?", z) for a in z: print("This is file", a, "in", z) print(open(x + "/" + a).read())` –  Dec 31 '20 at 13:20
  • Note that this won't print the contents if the supplied path is a file rather than a directory. – CrazyChucky Jan 18 '21 at 01:20
0

. I think the portal runs automated tests that pass it path names.

Sure, but that doesn't prevent it from giving you invalid input data, such as non-str or Path-like objects or non existing locations

Also, rather than using chdir, create the absolute path as you go using path.join

def displayFiles(filename):
    if filename and os.path.exists(filename):
        if os.path.isdir(filename):
            print("Directory name:", filename)
            for file in os.listdir(filename):
                child = os.path.join(filename,file) 
                displayFiles(child)
        else:
            print("File name:", filename, openFyle(filename))
    else:
        print("Invalid input")
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
0

Almost any time you're working with file system paths in Python, I recommend pathlib, because it's awesome. It doesn't make a huge difference this this case, but getting used to using it will make things much easier when you need to, say, join multiple paths together.

from pathlib import Path

def display_file(path):
    print(f'File: {path}\n')
    print(path.read_text())
    print('\n\n')

if __name__ == '__main__':
    path = Path(input('Enter a pathname: '))

    if path.is_dir():
        for item in path.iterdir():
            # This avoids attempting to print hidden files, which may exist
            # depending on the OS / filesystem.
            if item.is_file() and not item.name.startswith('.'):
                display_file(item)

    elif path.is_file():
        display_file(path)

The code only tries to print contents if the path is in fact a file or a directory; it displays nothing if passed an invalid or nonexistant path.

CrazyChucky
  • 3,263
  • 4
  • 11
  • 25