2017-10-23 2 views
1

click 패키지를 사용하여 Python으로 CLI를 작성하려고합니다. 내가 사용 파이썬 버전은 3.6Python 3.6에서 클릭 라이브러리가있는 모듈 오류가 없습니다.

이 내 응용 프로그램의 기본입니다 :

import os 
import click 

cmd_folder = os.path.join(os.path.dirname(__file__), 'commands') 


class IAMCLI(click.MultiCommand): 

    def list_commands(self, ctx): 
     rv = [] 
     for filename in os.listdir(cmd_folder): 
      if filename.endswith('.py') and \ 
        filename.startswith('cmd_'): 
       rv.append(filename[4:-3]) 
     rv.sort() 
     return rv 

    def get_command(self, ctx, cmd_name): 
     ns = {} 
     fn = os.path.join(cmd_folder, 'cmd_{}.py'.format(cmd_name)) 
     with open(fn) as f: 
      code = compile(f.read(), fn, 'exec') 
      eval(code, ns, ns) 
     return ns['cli'] 


@click.command(cls=IAMCLI) 
@click.option('--env', default='dev', type=click.Choice(['dev', 'staging', 'production']), 
       help='AWS Environment') 
@click.pass_context 
def cli(): 
    """AWS IAM roles and policies management CLI.""" 
    pass 


if __name__ == '__main__': 
    cli() 

를이 트리입니다 :

├── cli 
│   ├── __init__.py 
│   ├── aws 
│   │   ├── __init__.py 
│   │   ├── policy.py 
│   │   └── role.py 
│   ├── cli.py 
│   └── commands 
│    ├── __init__.py 
│    └── cmd_dump.py 

cmd_dump.py은 다음과 같습니다

import click 

from cli.aws.role import fetch_roles 


@click.command('dump', short_help='Dump IAM resources') 
@click.pass_context 
def cli(): 
    pass 

문제는 실행하려고 할 때입니다. python cli/cli.py --help 이것은 내가 얻은 것입니다 :

File "cli/commands/cmd_dump.py", line 3, in <module> 
    from cli.aws.role import fetch_roles 
ModuleNotFoundError: No module named 'cli.aws'; 'cli' is not a package 

그 밖의 생각은 없습니까?

+0

'cli.py'의 상위 디렉토리는'sys.path' 앞에 추가되므로 cli.py 스크립트에서'aws.role.fetch_roles'를 가져 오려고합니다. – vaultah

+0

여기서'os.path.join (cmd_folder, 'cmd _ {}. py '.format (cmd_name))'? – Mazzy

+0

해결 방법이 명확하지 않습니다. 어떤 생각? – Mazzy

답변

2

나는 새로운 파이썬 프로젝트의 개발을 시작할 때 나의 접근 방식에 따라 다른 대답을하려고합니다. 프로젝트를 배포 할 계획입니까 아니면 누군가와 공유하고 싶습니까? 당신이 경우에, 당신은 어떻게 생각하십니까 -이 사람이 명령

$ python path/to/project/codebase/cli/cli.py --help 

당신의 도구를 사용하기를 기억할 필요에 만족하실 것입니까? 그에게 명령을 기억하는 것이 더 쉬울까요

$ cli --help 

대신에?

난 당신이 바로 프로젝트의 포장을 시작하는 것이 좋습니다 - 최소한의 설치 스크립트를 작성 : 새로운 요구 사항이 등장 할 때

from setuptools import setup, find_packages 

setup(
    name='mypkg', 
    version='0.1', 
    packages=find_packages(), 
    install_requires=['click'], 
    entry_points={ 
     'console_scripts': ['cli=cli.cli:cli'], 
    }, 
) 

당신은 항상 당신의 설치 스크립트를 향상시킬 수 있습니다.당신의 코드베이스의 루트 디렉토리에 설치 스크립트를 놓고 :

├── setup.py 
├── cli 
│   ├── __init__.py 
│   ├── aws 
... 

지금 python setup.py develop 또는 더 나은합니다 ( setup.py 스크립트가) 코드베이스의 루트 디렉토리에서 pip install --editable=. 1를 실행합니다. 당신은 개발 모드에서 프로젝트를 설치하고 지금은 모든 수입은 (문제를 해결할 것이다)가 제대로 해결되지와

$ cli --help 

를 호출 할 수 있습니다. 그러나 그 외에도 많은 이점을 얻을 수 있습니다. 타겟 사용자에게 배포 할 준비가 될 수 있도록 프로젝트를 패키징하는 방법과 사용자가 방금 호출 한 것과 동일한 방식으로 호출 할 수있는 깨끗한 명령 행 인터페이스를 얻을 수 있습니다.

이제 프로젝트 개발을 계속하십시오. cli 명령의 코드를 변경하면 즉시 적용되므로 아무 것도 변경할 때마다 프로젝트를 다시 설치할 필요가 없습니다. 프로젝트의 개발 준비하고, 문제를 사용자에게 제공 할되면

:이 설치 wheel 파일로 프로젝트를 패키징 할

$ python setup.py bdist_wheel 

(당신은 할 wheel 패키지를 설치해야합니다 명령을 호출 할 수있는 : pip install wheel --user). 일반적으로 코드베이스 루트 디렉토리 하위 디렉토리 dist에 있습니다. 이 파일을 사용자에게 제공하십시오. 파일을 설치하려면, 그는

$ pip install Downloads/mypkg-0.1-py3-none.whl --user 

를 발행하고 목표 주가 시작 바로 도구를 사용할 수 있습니다 :

$ cli --help 

이는 매우 간단 설명하고 배울 수있는 많은 재료가 있지만, 그 과정을 안내하는 데 도움이되는 많은 자료가 있습니다.

주제에 대한 자세한 내용을 보려면 빠른 시작 참조로 우수 PyPA packaging guide을 권합니다. 포장용 click 명령은 their own docs are more than sufficient입니다.


  1. 나는 유통과 그 표준 도구로 적용 포장 개발에 pip를 사용하는 것이 좋습니다 것입니다.
+0

멋진 답변을 보내 주셔서 감사합니다. 명령 '파이썬 경로/to/project/codebase/cli/cli.py --help'가 모듈을 정확하게 해석하지 못한다는 점 – Mazzy

+0

네, 인터프리터를 통해 일반 스크립트로 호출하기 때문입니다. 필자가 설명한 방법은 명령 행 유틸리티를 호출 할 때 호출하는 것이므로 파이썬 스크립트로 취급 할 때 두통을 피할 수 있습니다. – hoefling

+0

프로젝트 구조를 전혀 변경할 필요가 없음에 유의하십시오. 이름 바꾸기가없고 파일을 옮길 필요가 없습니다. – hoefling

0

나는 이것을 100 번했다. 여러 레벨에서 패키지를 똑같은 이름으로 지정하는 것은 유혹스러운 일이지만 저항하지 마십시오! 요즘 내 패키지에 __main__.py이있는 경향이있어서 문제가 해결되는 데 도움이됩니다.

네임 스페이스 문제가 의심됩니다. 패키지 또는 내부 파일 cli.py의 이름을 변경하십시오. 이러한 변수를 사용하려고 시도하는 모든 가져 오기를 리팩토링해야합니다.

또한 함수 이름을 cli 이외의 것으로 변경하십시오. 같은 문제.

├── cli     <- rename this to 'my_app' or something else 
│ ├── __init__.py 
│ ├── aws 
│ │ ├── __init__.py 
│ │ ├── policy.py 
│ │ └── role.py 
│ ├── cli.py    <- or maybe it is easier to rename this 
│ └── commands 
│  ├── __init__.py 
│  └── cmd_dump.py 
+0

이유가 무엇입니까? 이름을 바꾸면 무엇을해야합니까? – Mazzy

+1

'ModuleNotFoundError : No'모듈에 'cli.aws'라는 오류가 발생했습니다. 'cli'는 패키지가 아닙니다.'실제로'cli.py' 안을 들여다보고 있습니다.'cli' 디렉토리가 아닙니다. 그래서 모듈이 발견되지 않습니다 ... 모듈을보고 있지 않습니다! 이상한 점은 cpython이 생성하는 순서에 따라 때로는 작동하고 때로는 작동하지 않는다는 것입니다. 보드 전체에 걸쳐 동일한 이름을 지정하지 마십시오. – slightlynybbled

+0

aws_iam_cli 폴더의 이름을 변경했지만 여전히 작동하지 않습니다. – Mazzy

1

패키지 안에 스크립트를 실행하지 마십시오! 패키지는 코드로 가져 오지 만 스크립트를 실행하지는 않습니다. 나머지는 가져 오기 오류와 관련이 없습니다. 예를 들어

:

├── cli # package 
│ ├── __init__.py 
│ ├── aws 
│ │ ├── __init__.py 
│ │ ├── policy.py 
│ │ └── role.py 
│ ├── cli.py 
│ │ └── commands 
│ │  ├── __init__.py 
│ │  └── cmd_dump.py 
├── run_this_module.py 

모듈 run_this_module.py을 실행하기 :

import cli 

"""Do your code here""" 
+0

이런 식으로'클릭 '을 실행할 지점은 실행을 중단한다는 것입니다. 'python main.py dump'를 실행하면 다음과 같은 오류가 발생합니다.'TypeError : cli()는 0 개의 위치 지정 인수를 가졌지 만 1은 주어졌습니다. ' – Mazzy

+0

소프트웨어 개발 작업을 간소화하기 위해이 간단한 규칙 (및 다른 많은 규칙)을 사용합니다. . 파이썬은 프로덕션을 위해 소프트웨어를 디자인 할 때 사용하는 언어입니다. 순수한 C 언어로 번역하기 위해 복사 및 붙여 넣기 명령이 필요합니다. –

관련 문제