Лучшее решение, чем если бы __name__ == '__main__' дважды в скрипте Python

У меня есть несколько скриптов Python, которые используют docopt.

Моя проблема заключается в том, что доступные параметры для двух сценариев немного отличаются - один параметр присутствует в одном сценарии, но не другой.

Я включил минимальный рабочий пример ниже.

Если я бегу:

python main.py --num=7 --name=John

скрипт не запускается, так как --name=John также передается в module1.py, где он недопустим.

С моим реальным сценарием у меня есть несколько импортов после того, как docopt анализирует аргументы, и поэтому я не могу просто переместить вызов docopt в конец сценария (if __name__ == '__main__':). Если я это сделаю, импорт в импортированном скрипте никогда не будет вызван, и я получаю неопределенные ошибки имени.

Я нашел обходной путь, но я не думаю, что это хорошая практика.

Что я делаю, это добавление:

if __name__ == '__main__':
    arguments = docopt.docopt(__doc__, version=0.1)

сразу после import docopt,

Тем не менее, я считаю, что использование двух из этих утверждений в сценарии является плохой практикой. Я не могу думать о каких-либо других обходных путях в это время все же.

Может кто-нибудь предложить лучшее решение? Заранее спасибо.

main.py

"""
main.py

Usage:
    main.py [--num=<num>] [--name=<name>] [--lib=<lib-dir>]
    main.py -h | --help
    main.py --version

Options:
    --num=<num>  A number
    --name=<name>  A name
    --lib=<lib-dir>  Path to the directory containing lib
    --version
"""
import docopt

arguments = docopt.docopt(__doc__, version=0.1)
library_path = os.path.abspath(arguments['--lib'])
sys.path.insert(1, library_path)
NUM = arguments['--num']

from other_file import x, y


from module1 import function


def main():
    print 'In main()'
    function()
    print NUM


if __name__ == '__main__':
    print '{} being executed directly'.format(__name__)
    main()

module1.py:

"""
module1.py

Usage:
    module1.py [--num=<num>] [--lib=<lib-dir>]
    module1.py -h | --help
    module1.py --version

Options:
    --num=<num>  A number
    --lib=<lib-dir>  Path to the directory containing lib
    --version
"""
import docopt

arguments = docopt.docopt(__doc__, version=0.1)
library_path = os.path.abspath(arguments['--lib'])
sys.path.insert(1, library_path)

NUM = arguments['--num']

from other_file import z


def main():
    print 'In main()'
    print NUM


def function():
    print 'In function in {}'.format(__name__)
    # print NUM


if __name__ == '__main__':
    print '{} being executed directly'.format(__name__)
    main()

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

Я забыл упомянуть, что модуль other_file имеет много разных версий. Из-за этого одним из параметров docopt является путь к файлу. Затем он добавляется в sys.path следующим образом:

library_path = os.path.abspath(arguments['--lib'])
sys.path.insert(1, library_path)

По этой причине импорт docopt в глобальную область необходим для добавления пути к модулю other_file в мой системный путь.

Глобальная переменная (NUM ниже, DEBUG в моем текущем файле), без которой я могу жить.

1 ответ

Чистое решение заключается в рефакторинге вашего кода, чтобы он не зависел от глобального, ни в main.py ни module1.py:

"""
main.py

Usage:
    main.py [--num=<num>] [--name=<name>]
    main.py -h | --help
    main.py --version

Options:
    --num=<num>  A number
    --name=<name>  A name
    --version
"""
from other_file import x, y
from module1 import function


def main(num):
    print 'In main()'
    function(num)
    print num


if __name__ == '__main__':
    import docopt

    arguments = docopt.docopt(__doc__, version=0.1)
    NUM = arguments['--num']

    print '{} being executed directly'.format(__name__)
    main(NUM)

А также:

"""
module1.py

Usage:
    module1.py [--num=<num>]
    module1.py -h | --help
    module1.py --version

Options:
    --num=<num>  A number
    --version
"""
from other_file import z


def main(num):
    print 'In main()'
    print num


def function(num):
    print 'In function in {}'.format(__name__)
    print num


if __name__ == '__main__':
    import docopt

    arguments = docopt.docopt(__doc__, version=0.1)
    NUM = arguments['--num']

    print '{} being executed directly'.format(__name__)
    main(NUM)
Другие вопросы по тегам