# Empty directories

Today I got asked if it was possible to recurse through a folder structure and find all the empty directories within that structure. It sounded like a simple job for os.walk, and it was.

The os.walk recurses a directory structure returning a 3-tuple for each directory (including the starting directory) containing the directory path, a list of all the directories from that path and a list of all the files from that path. An empty directory has no folders and no files in it so this gives us an easy condition

import os
for dirpath,dirs,files in os.walk(r'\\server\path\to\root\directory'):
if (len(dirs)+len(files)) == 0:
print(dirpath)


That lists all the empty directories to the screen but it would be more useful to have them in a list. Here the power of list comprehension comes into its own allowing us to do this with just one line of code

import os
emptydirs = [dirpath for dirpath,dirs,files in os.walk(r'\\server\path\to\root\directory') if (len(dirs)+len(files)) == 0]


# Modules

At the risk of simply repeating the document on modules, to run a method from a different python file you can use either of the following code snippets. The first gives you access to all the methods and variables inside of the file (note you don’t need the file extension) from within its own namespace. The second just the method you requested inside of your own namespace.

# Want access to all of the file's methods
import file
file.method_name()

# Just want a single method without anything
from file import method_name
method_name()


Both statements allow an optional as command to change the name. In the first case this changes the namespace (more on this later). The second changes the the name of the reference name for the method or variable. You will see the from … import a lot in code on the Internet although I tend to stay clear of it. There are a few things to be aware of

# Imports everything (with caveat) from file
from file import *

# does not work
from file import method_name,another_method as new_name,another_name

# new_name refers to another_method, method_name is no longer available
from file import method_name,another_method as new_name


However how do you get access to a python file that is not in the same directory as calling python script, or the PYTHONPATH environment variable / registry value? There are two variations.

The paths search are held in a list object called sys.path and can be manipulated at runtime. Just add the your required path to this list. Don’t replace the list or you’ll lose access to all your standard libraries. As an example, the following code allows you to import any python file from either C:\PythonModules or the modules directory off the

import sys,os
sys.path.append(r"C:\PythonModules")
# getcwd gets the current working directory and add modules directory
sys.path.append(os.path.join(os.getcwd(),"modules"))


If the file you wanted to import was in a sub-directory that is already in your search path you can use the package notation. This works no matter how deep inside the directory structure the file is. So you could a import a file from the sub-directory modules \ local \ custom with the following code. Notice as gives you a shortcut rather than typing in the full namespace each time.

import modules.local.custom.file as mymod
mymod.mymethod()


The limitation of this method is that each directory will need a __init__.py file in each directory. In the above example there would have to be a  __init__.py file the modules, local and custom directories. This file can be empty or can contain initialisation code where required but if it does not exist, the directory will not be searched.

Python 3 users also note that importing a module creates a __pycache__ directory in the files location where it stores the compiled .pyc file rather than storing it in the same directory as the file which it what happened previously. So in Python 3 the above would create __pycache__ directories in modules, local and custom.