The goal of this Python program is to:
Take in 2 Folder paths
Take in 1 Integer Value
Validate both Folders are in the directory and that the Integer value is an int
I'm using default values (Folder paths and int) as placeholders for testing but will be using CLI arguments at a later time.
My issue and questions are:
def validate_folders_arg(folder):
When both folders are present in the specified directory the program still prints "Folders cannot be found", Is this an issue with the "return None" statement? When 1 of the 2 or both folders is not in the specified directory the program should quit.
def validate_number_arg(number1):
This method is supposed to check an integer value was passed, if no integer value was found the program should automatically set the value to 10. Am I doing that correctly?
Main:
def main():
test()
Test method:
def test():
path1 = r"Path1"
path2 = r"Path2"
main_folder = validate_folders_arg(path1)
archive_folder = validate_folders_arg(path2)
kept_files = validate_number_arg(5)
# if any of the inputs is not valid return None
if main_folder is None or archive_folder is None:
print("Folders cannot be found")
Validate Folders:
def validate_folders_arg(folder):
"""validates folders in working directory"""
try:
isDir = os.path.isdir(folder)
print(isDir)
# return isDir
except Exception as e:
print(e)
return None
Validate int:
def validate_number_arg(number1):
input = number1
try:
int(input)
it_is = True
# return
except ValueError:
it_is = False
default_value = 10
return default_value
print(it_is)
Output:
True
True
True
Folders cannot be found
Related
I created a class and function. the function is creating a new object and executing other operations and returns the object.
class DoublyLinkedList:
def __init__(self, element):
self.item = element
self.before = None
self.after = None
def __str__(self):
if self.before is None:
return f'Previous node : {None}, item : {self.item}, Next node : {self.after.item};'
elif self.after is None:
return f'Previous node : {self.before.item}, item : {self.item}, Next node : {None};'
else:
return f'Previous node : {self.before.item}, item : {self.item}, Next node : {self.after.item};'
def addToHeadDLL(element, head):
try:
name = DoublyLinkedList(element)
except NameError:
print('Please enter correct parameters')
else:
head.before = name
name.after = head
print('List added to Head')
return name
a = DoublyLinkedList(1)
b = DoublyLinkedList(2)
a.after = b
b.before = a
c = addToHeadDLL(3, a) #Works
d = addToHeadDLL(4, e) #Produces NameError
When NameError occurs it has to print "Please enter correct parameters". But the output is like this,
List added to Head
Traceback (most recent call last):
File "c:/Users/JBallipalli/Desktop/Codes/dll.py", line 43, in <module>
d = addToHeadDLL(4, e)
NameError: name 'e' is not defined
Please help me solve this...
EDIT:
It's not that try-except- else not run in function. Check the following code. it does run.
import os
def openfolder(dir):
"""Opens folder in file explorer
Args:
dir (str): path of the folder
"""
os.startfile(dir)
def access(dir):
"""Checking access to the given directory
Args:
dir (str): directory path
Returns:
bool, list: status, list of files & folders in the directory path
"""
try:
filesList = os.listdir(dir)
except PermissionError:
print(f'No permission to access {os.path.basename(dir)}')
print(f'Please delete the file in {os.path.basename(dir)} manually')
folder = input('Do you wanna open folder in file explorer? type y/n : ')
if folder[0].lower() == 'y':
openfolder(dir)
return False, None
else:
return True, filesList
path = r'C:\Users\JBallipalli\Recent' # raises PermissionError
permission, files = access(path)
and check the output:
No permission to access Recent
Please delete the file in Recent manually
Do you wanna open folder in file explorer? type y/n :
The only difference between these two functions is above (DoublyLinkedList) code calls class inside a function and other doesn't. I want to know why its behaviour like that?
my Python version : 3.7.6
NameError is returned when you're calling function, as python doesn't know what to pass as e.
It never gets to the exception handling part in addToHeadDLL.
Do not use try and except in function,
If You want NameError then call function addToHeadDLL in try block.
Like that
try:
d = addToHeadDLL(4, e) #Produces NameError
except:
print("Name error")
To add to what everyone have said, you could modify you code like the sample below to fit your use case...
This time, you handle the error at function level...
def addToHeadDLL(element, head):
name = DoublyLinkedList(element)
if not isinstance(head, type(name)):
raise NameError('Please enter correct parameters')
head.before = name
name.after = head
print('List added to Head')
return name
a = DoublyLinkedList(1)
b = DoublyLinkedList(2)
a.after = b
b.before = a
try:
addToHeadDLL(4, e)
except NameError as e:
print(e)
I need help in writing a function (python preferably) to identify if a file is /etc/passwd or etc/shadow. So far I have tried using print(pw.getpwall()) but this reads the file from the os env. I need a library that takes input and can tell if a file is passwd/shadow file or not
passwd and shadow file format differs.
You can write a short function or class. First iteration would be:
Find root user, almost 100% true that root is the first entry
Check 2nd, 6th and 7th column (separator is : sign)
If 2nd is x and 6th is /root and 7th is /bin/*sh then it is a password file almost in 100%
If 2nd is a salt and hash (format: $salt$hash) and 6th is a number and 7th is empy then it is a shadow file almost in 100%
Naturally there could be problems:
Linux is configured not to use shadow file. In this case pasword file 2nd column contains the password
Linux is configured not to use salt (I guess is it possible or not)
Please check manuals: man 5 passwd and man 5 shadow
EDIT, 2020-04-24:
Here is the my corrected pwd.py:
#!/usr/bin/env python3
import os
import sys
passwd_file=('./passwd')
# path conversion handlers
def __nullpathconv(path):
return path
def __unixpathconv(path):
return path
# decide what field separator we can try to use - Unix standard, with
# the platform's path separator as an option. No special field conversion
# handler is required when using the platform's path separator as field
# separator, but are required for the home directory and shell fields when
# using the standard Unix (":") field separator.
__field_sep = {':': __unixpathconv}
if os.pathsep:
if os.pathsep != ':':
__field_sep[os.pathsep] = __nullpathconv
# helper routine to identify which separator character is in use
def __get_field_sep(record):
fs = None
for c in list(__field_sep.keys()):
# there should be 6 delimiter characters (for 7 fields)
if record.count(c) == 6:
fs = c
break
if fs:
return fs
else:
raise KeyError
# class to match the new record field name accessors.
# the resulting object is intended to behave like a read-only tuple,
# with each member also accessible by a field name.
class Passwd:
def __init__(self, name, passwd, uid, gid, gecos, dir, shell):
self.__dict__['pw_name'] = name
self.__dict__['pw_passwd'] = passwd
self.__dict__['pw_uid'] = uid
self.__dict__['pw_gid'] = gid
self.__dict__['pw_gecos'] = gecos
self.__dict__['pw_dir'] = dir
self.__dict__['pw_shell'] = shell
self.__dict__['_record'] = (self.pw_name, self.pw_passwd,
self.pw_uid, self.pw_gid,
self.pw_gecos, self.pw_dir,
self.pw_shell)
def __len__(self):
return 7
def __getitem__(self, key):
return self._record[key]
def __setattr__(self, name, value):
raise AttributeError('attribute read-only: %s' % name)
def __repr__(self):
return str(self._record)
def __cmp__(self, other):
this = str(self._record)
if this == other:
return 0
elif this < other:
return -1
else:
return 1
# read the whole file, parsing each entry into tuple form
# with dictionaries to speed recall by UID or passwd name
def __read_passwd_file():
if passwd_file:
passwd = open(passwd_file, 'r')
else:
raise KeyError
uidx = {}
namx = {}
sep = None
while 1:
entry = passwd.readline().strip()
if len(entry) > 6:
if sep is None:
sep = __get_field_sep(entry)
fields = entry.split(sep)
for i in (2, 3):
fields[i] = int(fields[i])
for i in (5, 6):
fields[i] = __field_sep[sep](fields[i])
record = Passwd(*fields)
if fields[2] not in uidx:
uidx[fields[2]] = record
if fields[0] not in namx:
namx[fields[0]] = record
elif len(entry) > 0:
pass # skip empty or malformed records
else:
break
passwd.close()
if len(uidx) == 0:
raise KeyError
return (uidx, namx)
# return the passwd database entry by UID
def getpwuid(uid):
u, n = __read_passwd_file()
return u[uid]
# return the passwd database entry by passwd name
def getpwnam(name):
u, n = __read_passwd_file()
return n[name]
# return all the passwd database entries
def getpwall():
u, n = __read_passwd_file()
return list(n.values())
# test harness
if __name__ == '__main__':
print(getpwall())
Apologies if this question has been asked before, but I wasn't able to find a similar question and hoped SO would recommend me one as I typed.
Scenario: Manually created folders with subfolder and files. At each level of folders I want to perform a particular function. Rather than raise an exception each time an error encountered, I'd like to print them out and continue the loop so I have a complete list of errors at the end.
Here is a MWE using simplified functions of what my code looks like:
import os, stat
def folder_info(folder):
if len(folder) > 20:
raise Exception('Folder {} name too long'.format(folder))
print(folder)
subfolders = os.listdir(folder)
return len(folder), subfolders
raise_error = False
folders = [f for f in os.listdir() if os.path.isdir(f)]
for folder in folders:
try:
length, subfolders = folder_info(folder)
except Exception as error:
if raise_error: raise
print('Error: {}'.format(error))
continue
for subfolder in subfolders:
subfolder = os.path.join(folder, subfolder)
try:
length, subfolders = folder_info(subfolder)
except Exception as error:
if raise_error: raise
print('Error: {}'.format(error))
continue
Ideally I'd like something where I don't have to type out a try and except statement for each nested loop. What I'm hoping for:
for folder in folders:
arg1, arg2 = exceptionwrapper(myfunction1(folder), raise_error)
for subfolder in arg2:
subfolder = os.path.join(folder, subfolder)
arg1, arg2, arg3 = exceptionwrapper(myfunction2(subfolder), raise_error)
for subsubfolder in arg3:
arg1, arg2 = exceptionwrapper(myfunction3(subsubfolders), raise_error)
I've tried following solutions with decorator functions but I wasn't able to pass in continue or figure out where it should go. This is my best attempt and I have a syntax error trying to pass in continue:
def exceptionwrapper(function, raise_error, after_error: function = continue):
def decorator(func):
def new_func(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as error:
if raise_error: raise
print('Error: {}'.format(error))
return after_error
return new_func
return decorator
Any help would be appreciated!
Your entire code can be written in few lines in a Pythonic way, if you could have used os.walk.
import os
for root, folders, files in os.walk(os.getcwd()):
for folder in folders:
print('dir is: ', folder)
try:
if len(folder) > 20:
raise Exception('Folder {} name too long'.format(folder))
except Exception as error_message:
print('Error in folder: {} due to: {}'.format(folder, error_message))
As you have specified in different folder level, you have to call different functions, you may try like below:
import os
curr_folder = os.getcwd()
for root, folders, files in os.walk(curr_folder):
for folder in folders:
print('dir is: ', folder)
folder_level = root[len(curr_folder)+1:].count(os.sep)
print('level is: ', folder_level)
if folder_level == 0:
# call myfunction0
pass
elif folder_level == 1:
# call myfunction1
pass
elif folder_level == 2:
# call myfunction2
pass
I built the following module for identifying if a file exists in a directory based on its size and name, all so I can use it in a different part of a project. When I try to use the function for the first time, it works great. But when I call it again, different variables with different parameters return the first answer. What am I missing?
Module:
import os
from stat import *
import math
CORRECT_PATH = ''
FLAG = 1
def check_matching(pathname, desired_file_name):
global FLAG
if desired_file_name in pathname:
FLAG = 0
return pathname
def walktree(dirz, desired_file_name, size):
global CORRECT_PATH
global FLAG
for f in os.listdir(dirz):
try:
if FLAG:
pathname = os.path.join(dirz, f)
mode = os.stat(pathname)[ST_MODE]
if S_ISDIR(mode):
# It's a directory, recourse into it
walktree(pathname, desired_file_name, size)
elif S_ISREG(mode):
# It's a file, call the callback function
new_size = int(os.path.getsize(pathname))
if (new_size - int(size)) < math.fabs(0.95*int(size)):
CORRECT_PATH = check_matching(pathname, desired_file_name)
else:
# Unknown file type, print a message
print 'Skipping %s' % pathname
else:
try:
CORRECT_PATH = CORRECT_PATH.replace('\\', '/')
return True, CORRECT_PATH
except WindowsError as w:
#print w
if w[0] == 5:
return True, CORRECT_PATH
except WindowsError as e:
pass
# print e
# if e[0] == 5:
# return True, CORRECT_PATH # add correct path now
return False, ''
Now when I call the this code (This is an example, I'm using two different text files, with different sizes and different names which are saved on my local computer):
import LS_FINAL_FOUR
ans = LS_FINAL_FOUR.walktree("C:/", "a_test", 38)
print ans # (True, 'C:/a_test.txt')
ans1 = LS_FINAL_FOUR.walktree("C:/", "a_sample", 1000000)
print ans1 # (True, 'C:/a_test.txt')
Both return the same output. Very frustrating. Does anyone know the reason behind this and how to solve it?
Edit: I'm almost certain it's a problem with the module, but I just can't lay my finger on it.
You need to reset the FLAG to 1 each time walktree is called. As it is, the FLAG is set to zero once when you find the first file. Each subsequent call, you re-access this initial result, since if FLAG is false, you run this code again:
else:
try:
CORRECT_PATH = CORRECT_PATH.replace('\\', '/')
return True, CORRECT_PATH
Since CORRECT_PATH is stored as a global, the initial answer persists after your walktree method returns.
I'd suggest fixing up the code by not using globals. Just make check_matching return a result directly to walktree, and don't cache the path result after walktree returns.
I made a function that searches files recursively and I want it to stop recursion when the first file is found:
def search_file(path):
for name in os.listdir(path):
sub = os.path.join(path, name)
if os.path.isfile(sub):
return sub#And break recursion
else:
search_file(sub)
Return a flag that says whether the file was found. When you call search_file, return if the return value is True.
You are close. You already break recursion when you find the file, the problem is that you didn't propegate that result all the way up the chain. A well-placed print statement would show what went wrong.
import os
def search_file(path):
for name in os.listdir(path):
sub = os.path.join(path, name)
print('peek at: {}'.format(sub))
if os.path.isfile(sub):
return sub#And break recursion
else:
sub = search_file(sub)
if sub:
return sub
print(search_file('a'))
Note that you need to be able to return a false entry in case it loops all the way down without finding anything. However, you do not want to break out of the for loop if nothing found in one subdirectory without checking the next sub directory. The return will break out of the function, returning the results without having to enter a break.
def search_file(path):
Initialize results to no file found
val = False
sub = None
for name in os.listdir(path):
sub = os.path.join(path, name)
val = os.path.isfile(sub):
if val:
return val, sub #And break recursion
else:
#check the subdirectory.
val, sub = search_file(sub)
# Break out if a valid file was found.
if val:
return val, sub
# No files found for this directory, return a failure
return val, sub
On the other hand, if you want to have only one return, you can use a break as follows
def search_file(path):
Initialize results to No file found
val = False
sub = None
for name in os.listdir(path):
sub = os.path.join(path, name)
val = os.path.isfile(sub):
if val:
break # break out of the for loop and return
else:
#check the subdirectory.
val, sub = search_file(sub)
# Break out if a valid file was found.
if val:
break
# Return the True or False results
return val, sub
I see a problem of not being able to return a value other than None once into the else: statement. Could you provide broader details describing what you are trying to do?
There is no way to simply exit recursion when you accomplish a task. Each recursive step that was opened must be closed before moving on. The function must return something (None or a value) to its caller.
I'm imagining this being a class method that sets value to an attribute because it doesn't return anything once recursion has begun. Here's what I would do in the instance that this is a class method.
def search_file(self, path):
for name in os.listdir(path):
sub = os.path.join(path, name)
if os.path.isfile(sub):
self.random_attr = sub
return True #And break recursion
elif search_file(sub):
break