Python setuptools: как вызвать функцию при импорте, но не при запуске из скрипта? - PullRequest
0 голосов
/ 17 мая 2018

Я хотел, чтобы в качестве

использовался только один файл pysome.py.

import pysome

и в консоли

$ pysome

В последнем случае я не хочу вызывать функцию, в первом случае я делаю.

У меня было

entry_points={'console_scripts': ['pysome=pysome:main']}

в setup.py. Я пытался

if __name__ != '__main__: some_fun()

но __name__ оказалось pysome, даже если вызывается как скрипт.

Тогда я попытался сделать пакет

setup.py pysome __init__.py __main__.py pysome.py

и изменил setup.py на

entry_points={'console_scripts': ['pysome=pysome.__main__:main']}

В __init__.py У меня

from .pysome import * some_fun()

и __main__.py просто

from .pysome import *

но при запуске pysome с консоли some_fun() все равно вызывается.

В случае упаковки вопрос будет: Как импортировать pysome в __main__.py без импорта __init__.py? Но решение без упаковки тоже было бы неплохо.

Используется Python 3.6.

1 Ответ

0 голосов
/ 17 мая 2018

введение shim

Самое чистое решение, которое приходит мне в голову, это введение функции shim точки входа, которая передает информацию о типе вызова в основную функцию.Что-то вроде

# pysome.py

def main(called_from_cli=False):
    if not called_from_cli:
        print('imported')
    else:
        print('called from cli')


def _entrypoint_main():
    main(called_from_cli=True)

Измените точку входа на _entrypoint_main в скрипте установки:

entry_points={'console_scripts': 'pysome=pysome:_entrypoint_main'}

Вызовите pysome.main() из кода как обычно.Если вы хотите разобраться в случае вызова pysome.main(called_from_cli=True), вы можете ввести глобальный флаг вместо функции arg и включать и выключать его в шимме.

извлечение информации о фрейме

Вы также можете проверить модуль вызывающего абонента - если это скрипт pysome, то main() вызывается из cli.Тем не менее, я думаю, что поведение inspect отличается в разных интерпретаторах, но я не уверен, что это именно так.

import inspect
import os


def main():
    frame = inspect.stack()[1]
    module = inspect.getmodule(frame[0])
    if module and os.path.basename(module.__file__) == 'pysome':
        print('called from cli')
    else:
        print('imported')

pkg_resources проверка (не рекомендуется)

Полагаю, вы могли быmain() проверьте, был ли pkg_resources импортирован перед вызовом main():

# pysome.py
import sys

def main():
    if 'pkg_resources' in sys.modules.keys():
        print('called from command line')
    else:
        print('called from code')

, но, конечно, это будет работать, только если вы не используете pkg_resources в своем коде, поэтому вызываете

import pkg_resources
import pysome

pysome.main()

сломает чек.Это делает вещи очень хрупкими, и я бы не советовал делать это.

...