Gil.I
Gil.I

Reputation: 884

Import file by file path entered by user

I am writing tester that run user scripts:

tester d:\scripts\test_scripts_list.txt

The test_scripts_list.txt looks like this:

test1
d:\123\test2

My program reads the command line with argparse module, reads each line of the test_scripts_list.txt and import each test file with __import__ (that actually runs the test file).
This is working well.

My only problem is to import d:\123\test2 that's gives me:

ImportError: Import by filename is not supported.

I think this can be solved by analyze the path name, add it to PYTHONPATH while running with sys.path.append and than import it. But it seems a complicated soultion.
Do you have a better idea?

Note: test1's path is already in PYTHONPATH

EDIT My current solution:

# Go over each line in scripts_filename and import all tests
for line in open(scripts_file.scripts_filename):
    line = line.strip()

    if not line or  line[0] == '#':
        # Ignore empty line and line with comment
        continue
    elif line[1] == ':' and  line[2] == '\\':
        # Find the last position of '\\'
        file_name_pos =  line.rfind('\\')
        # Separate file path and filename (I.E [0:5] will take 4 first chars and [4:] will take all chars except the 4 chars)
        file_path_string =  line[0:file_name_pos+1]
        file_name_string =  line[file_name_pos+1:]
        # Append file_path_string to PYTHONPATH in order to import it later
        sys.path.append(file_path_string)

        import_name  =  file_name_string
    else:
        import_name =  line

    try:
        # Try to import test
        print  "Run test : %s" % line
        __import__(import_name)
    except ImportError:
        print "Failed! (Test not found). Continue to the next test"

Upvotes: 2

Views: 413

Answers (1)

Martin Geisler
Martin Geisler

Reputation: 73748

See the imp module, in particular the imp.load_module and imp.load_source functions. Here's one way you can use them (from Mercurial's source code, slightly simplified):

def loadpath(path):
    module_name = os.path.basename(path)[:-3]
    if os.path.isdir(path):
        # module/__init__.py style
        d, f = os.path.split(path.rstrip('/'))
        fd, fpath, desc = imp.find_module(f, [d])
        return imp.load_module(module_name, fd, fpath, desc)
    else:
        return imp.load_source(module_name, path)

Upvotes: 3

Related Questions