The following code arose through a discovery phase, but its problems were never resolved, as it wasn't needed at the time.
On rediscovering its problems, however, it seemed like a decent example for more experienced developers to use as a launch point for schooling in one or more best practices using os.scandir(), the 'newer', or more generally acceptable method over os.listdir(). As an aside to the questions below, if you can explain why one is preferred over the other, or how they are or are not complementary, your views are welcome.
Some commented code remains, showing another attempt at inserting the node type at the beginning of the string. The while loop did not work out so well, but it does function. How to explain the why of it not working and what should replace its replacement, if anything more than greater fluency of the presently used functions, will go a long way to helping iron this out.
Main concerns are listed below with the core questions I have about making this monstrosity work for me in the development of more refined Python skills.
Thanks in advance.
import os
import time
basedir = os.path.dirname(__file__)
def scandir_list(basedir):
entries = os.scandir(basedir)
# print(entries)
# <posix.ScandirIterator object at 0x7f5f7d0fe5e0>
# The ScandirIterator points to all the entries in the current directory.
# Loop the iterator and print out the content.
with os.scandir(basedir) as entries:
for entry in entries:
def filetype(entry):
# result = ""
# while result == "" or result == None:
print('dir ' if os.path.isdir(entry) else '' , end="")
print('file ' if os.path.isfile(entry) else '' , end="")
print('link ' if os.path.islink(entry) else '' , end="")
print('.. ' if os.path.ismount(entry) else '' , end="")
# result = 'dir ' if os.path.isdir(entry) else '' #, end="")
# result = 'file ' if os.path.isfile(entry) else '' #, end="")
# result = 'link ' if os.path.islink(entry) else ' ' #, end=""
# result = '.. ' if os.path.ismount(entry) else ' ' #, end="")
# print('result: ', result)
# return result
resourcetype = filetype(entry)
size = round(float(os.path.getsize(entry)/1024), 2) # does .2f formatting demonstrate presentation layer bias?
lastmodified = time.ctime(os.path.getmtime(entry))
# print(f"{resourcetype}: {entry.name} \t\t\t\t\t Size: {os.path.getsize(entry)/1024:.2f} \t \t \t Last Modified: {time.ctime(os.path.getmtime(entry))}")
print("{}: Size: {} kb, Last Modified: {}, Name: {}".format(resourcetype, size, lastmodified, entry.name))
scandir_list(basedir)
Renders output like so:
file None: Size: 5.76 kb, Last Modified: Sat Sep 25 07:07:28 2021, Name: app.py
dir None: Size: 4.0 kb, Last Modified: Fri Sep 24 23:59:23 2021, Name: test
dir None: Size: 4.0 kb, Last Modified: Sat Sep 25 04:15:51 2021, Name: views
The Problems:
(Just to be clear, the code here is about testing limits, so the method may simply present a wrong way to start...)
1.) Because the resource name is of variable length, and tabs (\t) inserted into the string format are relative (without stops), the resource name has been tacked on to the end. The desired outcome is to place the resource name in the second slot. How can resource name be put into the second slot and the string formatted in such as way as to avoid jagged edges, with minimal code -- whatever the refactor requires in terms of reorganization, or an altogether different approach?
2.) The first slot, resource name, is accompanied by None, but the cause (other print statements inline to the formation of the string) is not well known. What is your explanation and workaround?
UPDATE:
The code originally presented is intact, for all of its having tons of commented statements, mainly, it was thought, for the alternates to be reconstructed.
One way to get rid of None
is below. The code is a bit cleaner, too, but the function and its call which have been 'flattened' out remain just in case...
import os
import time
basedir = os.path.dirname(__file__)
def scandir_list(basedir):
with os.scandir(basedir) as entries:
for entry in entries:
resdict = dict()
resdict.update({'res': 'dir'}) if entry.is_dir() else ''
resdict.update({'res': 'file'}) if entry.is_file() else ''
resdict.update({'res': 'link'}) if entry.is_symlink() else ''
# resdict.update({'res': '..'}) if os.path.ismount(entry) else ''
resourcetype = resdict['res']
# print("resdict: ", resdict) # what's it look like?
size = round(float(os.path.getsize(entry)/1024), 2)
lastmodified = time.ctime(os.path.getmtime(entry))
print("{}: Size: {} kb, Last Modified: {}, Name: {}".format(resourcetype, size, lastmodified, entry.name))
# del resdict # not really necessary
if __name__ == "__main__":
scandir_list(basedir)
Try this code: Your error is that your function return 'None', because you don t have return in it. Don t confuse a print and a return.
Please find bellow your code with best practices:
import os
import time
def scandir_list(dir_path):
result = ""
for entry in os.scandir(dir_path):
stats = entry.stat()
result += f"""{
(
[
filetype
for filetype in ['dir', 'file', 'mount', 'link']
if getattr(os.path, f"is{filetype}")(entry)
] +
["Unknow"]
)[0]
}\tSize: {
round(float(os.path.getsize(entry)/1024), 2)
}kb\tLast Modified: {
time.ctime(stats.st_mtime)
}\tName: {entry.name}\n"""
return result
if __name__ == "__main__":
print(scandir_list(os.path.dirname(__file__)))
Here my output:
dir Size: 16.0kb Last Modified: Fri Sep 24 10:17:24 2021 Name: xxx
dir Size: 28.0kb Last Modified: Tue Sep 7 12:15:40 2021 Name: yyy
dir Size: 4.0kb Last Modified: Fri Sep 24 11:00:04 2021 Name: zzz
dir Size: 28.0kb Last Modified: Tue Jun 15 22:16:15 2021 Name: aaa
dir Size: 4.0kb Last Modified: Thu Mar 18 14:54:12 2021 Name: bbb
dir Size: 4.0kb Last Modified: Tue Jul 28 22:12:35 2020 Name: ccc
file Size: 2.22kb Last Modified: Thu Jul 22 15:44:15 2021 Name: ddd.py