我想检测模块是否发生了变化。现在,使用inotify很简单,你只需要知道你想从哪个目录获取通知。

如何在python中检索模块的路径?


当前回答

正如其他答案所说,最好的方法是使用__file__(下面再次演示)。然而,有一个重要的警告,即如果你单独运行模块(即作为__main__), __file__是不存在的。

例如,假设你有两个文件(都在你的PYTHONPATH上):

#/path1/foo.py
import bar
print(bar.__file__)

and

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

运行foo.py会得到如下输出:

/path1        # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs

然而,如果你试图单独运行bar.py,你会得到:

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

希望这能有所帮助。在测试其他解决方案时,这个警告花费了我大量的时间和混乱。

其他回答

正如其他答案所说,最好的方法是使用__file__(下面再次演示)。然而,有一个重要的警告,即如果你单独运行模块(即作为__main__), __file__是不存在的。

例如,假设你有两个文件(都在你的PYTHONPATH上):

#/path1/foo.py
import bar
print(bar.__file__)

and

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

运行foo.py会得到如下输出:

/path1        # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs

然而,如果你试图单独运行bar.py,你会得到:

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

希望这能有所帮助。在测试其他解决方案时,这个警告花费了我大量的时间和混乱。

我不明白为什么没有人谈论这个,但对我来说,最简单的解决方案是使用imp.find_module("modulename")(文档在这里):

import imp
imp.find_module("os")

它给出了一个位于第二位置的元组:

(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))

与“inspect”方法相比,此方法的优点是您不需要导入模块来使其工作,并且可以在输入中使用字符串。例如,在检查另一个脚本中调用的模块时非常有用。

编辑:

在python3中,importlib模块应该这样做:

importlib.util.find_spec的文档:

Return the spec for the specified module. First, sys.modules is checked to see if the module was already imported. If so, then sys.modules[name].spec is returned. If that happens to be set to None, then ValueError is raised. If the module is not in sys.modules, then sys.meta_path is searched for a suitable spec with the value of 'path' given to the finders. None is returned if no spec could be found. If the name is for submodule (contains a dot), the parent module is automatically imported. The name and package arguments work the same as importlib.import_module(). In other words, relative module names (with leading dots) work.

下面是一个快速bash脚本,以防它对任何人都有用。我只是想设置一个环境变量,这样我就能把它推到代码中。

#!/bin/bash
module=${1:?"I need a module name"}

python << EOI
import $module
import os
print os.path.dirname($module.__file__)
EOI

壳牌的例子:

[root@sri-4625-0004 ~]# export LXML=$(get_python_path.sh lxml)
[root@sri-4625-0004 ~]# echo $LXML
/usr/lib64/python2.7/site-packages/lxml
[root@sri-4625-0004 ~]#
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)

从python包的模块中,我必须引用与包位于同一目录中的文件。前女友。

some_dir/
  maincli.py
  top_package/
    __init__.py
    level_one_a/
      __init__.py
      my_lib_a.py
      level_two/
        __init__.py
        hello_world.py
    level_one_b/
      __init__.py
      my_lib_b.py

所以在上面,我必须从my_lib_a.py模块调用maincli.py,知道top_package和maincli.py在同一个目录中。下面是我获取main .py路径的方法:

import sys
import os
import imp


class ConfigurationException(Exception):
    pass


# inside of my_lib_a.py
def get_maincli_path():
    maincli_path = os.path.abspath(imp.find_module('maincli')[1])
    # top_package = __package__.split('.')[0]
    # mod = sys.modules.get(top_package)
    # modfile = mod.__file__
    # pkg_in_dir = os.path.dirname(os.path.dirname(os.path.abspath(modfile)))
    # maincli_path = os.path.join(pkg_in_dir, 'maincli.py')

    if not os.path.exists(maincli_path):
        err_msg = 'This script expects that "maincli.py" be installed to the '\
        'same directory: "{0}"'.format(maincli_path)
        raise ConfigurationException(err_msg)

    return maincli_path

根据PlasmaBinturong的帖子,我修改了代码。