Вопрос

Я хочу определить, изменился ли модуль.Теперь использовать inotify очень просто: вам просто нужно знать каталог, из которого вы хотите получать уведомления.

Как получить путь к модулю в Python?

Это было полезно?

Решение

import a_module
print(a_module.__file__)

На самом деле даст вам путь к файлу .pyc, который был загружен, по крайней мере, в Mac OS X. Так что я думаю, вы можете сделать:

import os
path = os.path.dirname(a_module.__file__)

Вы также можете попробовать:

path = os.path.abspath(a_module.__file__)

Получить каталог модуля.

Другие советы

Есть inspect модуль на питоне.

Официальная документация

Модуль Inspect предоставляет несколько полезных функций, чтобы помочь получить информацию о живых объектах, таких как модули, классы, методы, функции, трассировки, объекты кадров и объекты кода.Например, это может помочь вам изучить содержимое класса, получить исходный код метода, извлечь и отформатировать список аргументов для функции или получить всю информацию, необходимую для отображения подробного трасса.

Пример:

>>> import os
>>> import inspect
>>> inspect.getfile(os)
'/usr/lib64/python2.7/os.pyc'
>>> inspect.getfile(inspect)
'/usr/lib64/python2.7/inspect.pyc'
>>> os.path.dirname(inspect.getfile(inspect))
'/usr/lib64/python2.7'

Как уже говорилось в других ответах, лучший способ сделать это - с помощью __file__ (еще раз продемонстрировано ниже).Однако есть важная оговорка, заключающаяся в том, что __file__ НЕ существует, если вы запускаете модуль самостоятельно (т.е.как __main__).

Например, предположим, что у вас есть два файла (оба находятся в вашем PYTHONPATH):

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

и

#/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 

Надеюсь это поможет.Это предостережение стоило мне много времени и путаницы при тестировании других представленных решений.

Я постараюсь также рассмотреть несколько вариантов этого вопроса:

<Ол>
  • поиск пути к вызываемому скрипту
  • найти путь к исполняемому в данный момент скрипту
  • поиск каталога вызываемого скрипта
  • (Некоторые из этих вопросов были заданы в SO, но были закрыты как дубликаты и перенаправлены здесь.)

    Предостережения об использовании __ file __

    Для модуля, который вы импортировали:

    import something
    something.__file__ 
    

    вернет абсолютный путь модуля. Однако, учитывая следующий скрипт foo.py:

    #foo.py
    print '__file__', __file__
    

    Вызов его с помощью «python foo.py» вернет просто «foo.py». Если вы добавите Шебанг:

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

    и вызовите его с помощью ./foo.py, он вернет './foo.py'. Вызов его из другого каталога (например, поместите foo.py в строку каталога), а затем вызов

    python bar/foo.py
    

    или добавление шебанга и непосредственное выполнение файла:

    bar/foo.py
    

    вернет 'bar / foo.py' ( относительный путь).

    Поиск каталога

    Теперь перейдя оттуда к каталогу, os.path.dirname (__ file __) также может быть сложным. По крайней мере, в моей системе она возвращает пустую строку, если вы вызываете ее из того же каталога, что и файл. напр.

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

    выведет:

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

    Другими словами, он возвращает пустую строку, поэтому это не кажется надежным, если вы хотите использовать его для текущего файла (в отличие от файла из импортированный модуль). Чтобы обойти это, вы можете обернуть это в вызов 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__))
    

    который выводит что-то вроде:

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

    Обратите внимание, что abspath () НЕ разрешает символические ссылки. Если вы хотите сделать это, используйте вместо этого realpath (). Например, создание символической ссылки file_import_testing_link, указывающей на file_import_testing.py, со следующим содержимым:

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

    выполнение будет печатать абсолютные пути что-то вроде:

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

    file_import_testing_link - > file_import_testing.py

    Использование inspect

    @SummerBreeze упоминает об использовании модуля inspect .

    Похоже, это хорошо работает и довольно кратко для импортированных модулей:

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

    послушно возвращает абсолютный путь. Однако, чтобы найти путь к исполняемому в данный момент скрипту, я не нашел способа его использовать.

    Я не понимаю, почему никто об этом не говорит, но для меня самое простое решение — использовать imp.find_module("имя_модуля") (документация здесь):

    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))
    

    Преимущество этого метода перед «проверкой» заключается в том, что вам не нужно импортировать модуль, чтобы он работал, и вы можете использовать строку на входе.Полезно, например, при проверке модулей, вызванных в другом скрипте.

    РЕДАКТИРОВАТЬ:

    В Python3 importlib модуль должен сделать:

    Док. importlib.util.find_spec:

    Возвращает спецификацию для указанного модуля.

    Сначала sys.modules проверяется, был ли уже импортирован модуль.Если да, то sys.modules[имя].спецификация возвращается.Если это не установлено, то ValueError поднимается.Если модуль не находится в Sys.Modules, то sys.meta_path ищет подходящую спецификацию со значением «пути», данным искателям.Ни один не возвращается, если спецификация не может быть найдена.

    Если имя предназначено для подмодуля (содержит точку), родительский модуль автоматически импортируется.

    Аргументы имени и пакета работают так же, как importlib.import_module().Другими словами, работают относительные имена модулей (с точкой в ​​начале).

    Это было тривиально.

    У каждого модуля есть переменная __ file __ , которая показывает относительный путь от того места, где вы сейчас находитесь.

    Следовательно, получить каталог для модуля, чтобы уведомить его, просто:

    os.path.dirname(__file__)
    
    import os
    path = os.path.abspath(__file__)
    dir_path = os.path.dirname(path)
    

    Утилита командной строки

    Вы можете настроить его на утилиту командной строки,

    python-which <package name>
    

     введите описание изображения здесь

    <Ч>

    Создайте / usr / local / bin / python-which

    #!/usr/bin/env python
    
    import importlib
    import os
    import sys
    
    args = sys.argv[1:]
    if len(args) > 0:
        module = importlib.import_module(args[0])
        print os.path.dirname(module.__file__)
    

    Сделайте его исполняемым

    sudo chmod +x /usr/local/bin/python-which
    

    Так что я потратил немало времени, пытаясь сделать это с py2exe Проблема заключалась в том, чтобы получить базовую папку сценария, независимо от того, выполнялся ли он как сценарий python или как исполняемый файл py2exe. Кроме того, чтобы он работал независимо от того, запускается ли он из текущей папки, другой папки или (это было наиболее сложно) из системного пути.

    В конце концов я использовал этот подход, используя sys.frozen в качестве индикатора работы в py2exe:

    import os,sys
    if hasattr(sys,'frozen'): # only when running in py2exe this exists
        base = sys.prefix
    else: # otherwise this is a regular python script
        base = os.path.dirname(os.path.realpath(__file__))
    
    import module
    print module.__path__
    
      

    Пакеты поддерживают еще один специальный атрибут, __ path __ . Это   инициализируется как список, содержащий имя каталога, содержащего   пакет & # 8217; s __ init __. py перед выполнением кода в этом файле.   Эта переменная может быть изменена; это влияет на будущие поиски   модули и подпакеты, содержащиеся в упаковке.

         

    Хотя эта функция не требуется часто, ее можно использовать для расширения   набор модулей найден в пакете.

    источник

    вы можете просто импортировать свой модуль затем нажмите на его имя, и вы получите его полный путь

    >>> import os
    >>> os
    <module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
    >>>
    

    Если единственное предостережение относительно использования __ file __ - это когда текущий относительный каталог пуст (то есть, когда он запускается как скрипт из того же каталога, где находится скрипт), тогда тривиальное решение:

    import os.path
    mydir = os.path.dirname(__file__) or '.'
    full  = os.path.abspath(mydir)
    print __file__, mydir, full
    

    И результат:

    $ python teste.py 
    teste.py . /home/user/work/teste
    

    Трюк в или '.' после вызова dirname () . Он устанавливает каталог как . , что означает текущий каталог , и является допустимым каталогом для любой связанной с путем функции.

    Таким образом, использование abspath () действительно не нужно. Но если вы все равно его используете, уловка не нужна: abspath () принимает пустые пути и правильно интерпретирует его как текущий каталог.

    Я хотел бы внести свой вклад в один распространенный сценарий (в Python 3) и изучить несколько подходов к нему.

    Встроенная функция открыть() принимает относительный или абсолютный путь в качестве первого аргумента.Относительный путь рассматривается как относительно текущего рабочего каталога хотя поэтому рекомендуется передавать абсолютный путь к файлу.

    Проще говоря, если вы запустите файл сценария со следующим кодом, это нет гарантировал, что example.txt файл будет создан в том же каталоге, где находится файл сценария:

    with open('example.txt', 'w'):
        pass
    

    Чтобы исправить этот код, нам нужно получить путь к скрипту и сделать его абсолютным.Чтобы обеспечить абсолютный путь, мы просто используем ОС.путь.реальный путь() функция.Чтобы получить путь к скрипту, существует несколько общих функций, которые возвращают различные результаты пути:

    • os.getcwd()
    • os.path.realpath('example.txt')
    • sys.argv[0]
    • __file__

    Обе функции os.getcwd() и ОС.путь.реальный путь() результаты обратного пути на основе текущий рабочий каталог.В общем, это не то, что мы хотим.Первый элемент sys.argv список - это путь к корневому скрипту (скрипт, который вы запускаете) независимо от того, вызываете ли вы список в самом корневом скрипте или в каком-либо из его модулей.Это может пригодиться в некоторых ситуациях.А __файл__ переменная содержит путь к модулю, из которого она была вызвана.


    Следующий код правильно создает файл example.txt в том же каталоге, где находится скрипт:

    filedir = os.path.dirname(os.path.realpath(__file__))
    filepath = os.path.join(filedir, 'example.txt')
    
    with open(filepath, 'w'):
        pass
    

    Внутри модулей пакета 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
    

    Итак, выше я должен был вызвать maincli.py из модуля my_lib_a.py, зная, что top_package и maincli.py находятся в одном каталоге. Вот как я могу получить путь к maincli.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 я изменил код.

    Если вы хотите сделать это динамически в программе " попробуйте этот код:
    Моя точка зрения такова, что вы можете не знать точное название модуля для «жесткого кода» Это. Он может быть выбран из списка или может не работать в данный момент для использования __file __.

    (я знаю, это не будет работать в Python 3)

    global modpath
    modname = 'os' #This can be any module name on the fly
    #Create a file called "modname.py"
    f=open("modname.py","w")
    f.write("import "+modname+"\n")
    f.write("modpath = "+modname+"\n")
    f.close()
    #Call the file with execfile()
    execfile('modname.py')
    print modpath
    <module 'os' from 'C:\Python27\lib\os.pyc'>
    

    Я пытался избавиться от " глобального " проблема, но обнаружил случаи, когда это не сработало Я думаю, что "execfile ()" можно эмулировать в Python 3 Поскольку это в программе, его можно легко вставить в метод или модуль для повторного использования.

    Если вы хотите узнать абсолютный путь из своего скрипта, вы можете использовать путь объект:

    from pathlib import Path
    
    print(Path().absolute())
    print(Path().resolve('.'))
    print(Path().cwd())
    

    метод cwd ()

      

    Возвращает новый объект пути, представляющий текущий каталог (как возвращено os.getcwd ())

    метод resol ()

      

    Сделайте путь абсолютным, разрешив любые символические ссылки. Возвращается новый объект пути:

    Если вы хотите получить корневой путь пакета из любого из его модулей, работает следующее (проверено на Python 3.6):

    from . import __path__ as ROOT_PATH
    print(ROOT_PATH)
    

    На основной путь __ init __. py также можно ссылаться, используя вместо этого __ file __ .

    Надеюсь, это поможет!

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top