Лучшее решение, чем если бы __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)