How to retrieve a module's path?

后端 未结 20 2210
无人及你
无人及你 2020-11-22 05:34

I want to detect whether module has changed. Now, using inotify is simple, you just need to know the directory you want to get notifications from.

How do I retrieve

20条回答
  •  深忆病人
    2020-11-22 06:09

    I will try tackling a few variations on this question as well:

    1. finding the path of the called script
    2. finding the path of the currently executing script
    3. finding the directory of the called script

    (Some of these questions have been asked on SO, but have been closed as duplicates and redirected here.)

    Caveats of Using __file__

    For a module that you have imported:

    import something
    something.__file__ 
    

    will return the absolute path of the module. However, given the folowing script foo.py:

    #foo.py
    print '__file__', __file__
    

    Calling it with 'python foo.py' Will return simply 'foo.py'. If you add a shebang:

    #!/usr/bin/python 
    #foo.py
    print '__file__', __file__
    

    and call it using ./foo.py, it will return './foo.py'. Calling it from a different directory, (eg put foo.py in directory bar), then calling either

    python bar/foo.py
    

    or adding a shebang and executing the file directly:

    bar/foo.py
    

    will return 'bar/foo.py' (the relative path).

    Finding the directory

    Now going from there to get the directory, os.path.dirname(__file__) can also be tricky. At least on my system, it returns an empty string if you call it from the same directory as the file. ex.

    # foo.py
    import os
    print '__file__ is:', __file__
    print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)
    

    will output:

    __file__ is: foo.py
    os.path.dirname(__file__) is: 
    

    In other words, it returns an empty string, so this does not seem reliable if you want to use it for the current file (as opposed to the file of an imported module). To get around this, you can wrap it in a call to abspath:

    # foo.py
    import os
    print 'os.path.abspath(__file__) is:', os.path.abspath(__file__)
    print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))
    

    which outputs something like:

    os.path.abspath(__file__) is: /home/user/bar/foo.py
    os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar
    

    Note that abspath() does NOT resolve symlinks. If you want to do this, use realpath() instead. For example, making a symlink file_import_testing_link pointing to file_import_testing.py, with the following content:

    import os
    print 'abspath(__file__)',os.path.abspath(__file__)
    print 'realpath(__file__)',os.path.realpath(__file__)
    

    executing will print absolute paths something like:

    abspath(__file__) /home/user/file_test_link
    realpath(__file__) /home/user/file_test.py
    

    file_import_testing_link -> file_import_testing.py

    Using inspect

    @SummerBreeze mentions using the inspect module.

    This seems to work well, and is quite concise, for imported modules:

    import os
    import inspect
    print 'inspect.getfile(os) is:', inspect.getfile(os)
    

    obediently returns the absolute path. For finding the path of the currently executing script:

    inspect.getfile(inspect.currentframe())
    

    (thanks @jbochi)

提交回复
热议问题