2013-08-06 6 views
21

프로젝트 내에 Python 스크립트 패밀리를 작성 중입니다. 각 스크립트는과 같이 프로젝트의 서브 디렉토리 내에 : 스크립트의Python : 스크립트의 계열간에 공통 코드를 공유합니다.

projectroot 
    | 
    |- subproject1 
    | | 
    | |- script1.main.py 
    | `- script1.merger.py 
    | 
    |- subproject2 
    | | 
    | |- script2.main.py 
    | |- script2.matcher.py 
    | `- script2.merger.py 
    | 
    `- subproject3 
     | 
     |- script3.main.py 
     |- script3.converter.py 
     |- script3.matcher.py 
     `- script3.merger.py 

이제 몇 몇 가지 코드를 공유 할 수 있습니다. 공유 코드는 프로젝트 자체의 일부로 간주되는 것이 가장 좋습니다. 개별적으로 컴파일하고 라이브러리를 만들거나, 사이트 전체에서 PYTHONPATH로 드롭하는 것은 아닙니다. 그 코드를 projectroot 디렉토리 나 projectroot의 하위 디렉토리 (예 : common)에 여러 위치에 배치 할 수 있습니다.

그러나, 지금까지의 생각하는 방법의 대부분은 빈 내 하위 프로젝트에서 __init__.py 파일을 패키지를 만들고 상대의 수입을 사용하여 (또는 중복 모든 하위 프로젝트에 sys.path 덤비는 포함한다. 더 나쁜, 그것은 패키지 구조를 구축하는 것 같아 스크립트의 가족은 거부 PEP-3122에서 다음과 같은 경고의 충돌하여 실행 주위 :

Attention! This PEP has been rejected. Guido views running scripts within a package as an anti-pattern.

패키지 내에서 스크립트 내가 같은에서 공통 코드를 유지하는 방식으로 일을 설정하는 방법 안티 patternish 인 경우 프로젝트 또는 모듈 및 패키지 기반 시스템을 여기에서 수용 할 수 있습니까? 어느 것이 가장 깨끗한 접근 방식입니까? (FWIW o 프로젝트 디렉토리에 shared.py 또는 common.py과 같은 파일이 있습니다.

+1

django는 모든 스크립트를 실행하기 위해'manage.py'라는 중앙 집중식 엔트리 포인트를 사용한다고 생각합니다. 이와 같이하면'subprojectX'를 패키지로 만들고,''manage.py' (엔트리 포인트) 스크립트 내부에서 집중적으로 가져 오기를 처리 할 수 ​​있습니다. 패키지로서, 공유 기능이 살아갈 수있는'공통 '모듈을 쉽게 지원할 것이라고 나는 믿는다. – dm03514

+1

나는 이것이 PEP-32122가 아니라 [PEP-3122] (https://www.python.org/dev/peps/pep-3122/)이어야한다고 생각한다. – user1071847

답변

19

프로젝트의 최상위 레벨에 간단한 "실행기"스크립트를 배치하고 각 하위 프로젝트 폴더를 패키지로 만드는 것이 좋습니다. 패키지의 모듈은 서로 가져 오거나 공통 코드를 common 패키지로 가져올 수 있습니다.

projectroot 
    |- script1.py # launcher scripts, see below for example code 
    |- script2.py 
    |- script3.py 
    | 
    |- common 
    | |- __init__.py 
    | |- merger.py # from other packages, use from ..common import merger to get this 
    | 
    |- subproject1 
    | |- __init__.py # this can be empty 
    | |- script1_main.py 
    | 
    |- subproject2 
    | |- __init__.py 
    | |- script2_main.py 
    | |- script2_matcher.py 
    | 
    |- subproject3 
     |- __init__.py 
     |- script3_main.py 
     |- script3_converter.py 
     |- script3_matcher.py 

런처 스크립트는 매우 간단 할 수있다 : 여기

우리가 다양한 merger 모듈은 공유 버전으로 리팩토링 할 수있다 가정하면 구조는 같을 것이다 무엇

from subproject1 import script1_main 

if __name__ == "__main__": 
    script1_main.main() 

그 즉, 적절한 "scriptN_main"모듈을 가져 와서 함수를 실행하는 것입니다. main 모듈은 .pyc 파일에 캐시 된 컴파일 된 바이트 코드를 가질 수 있기 때문에 간단한 스크립트를 사용하면 스크립트 시작 속도에 약간의 이점이있을 수 있지만 스크립트는 캐시되지 않습니다.

참고 : . 문자의 경우 _자를 바꿔 모듈의 이름을 변경했습니다. Python은 속성 액세스를 나타 내기를 기대하기 때문에 식별자 (예 : 모듈 이름)에 .을 사용할 수 없습니다. 즉, 해당 모듈을 가져올 수 없었습니다. (이건 예제 파일의 유물 일 뿐이므로 실제 코드에있는 것은 아닙니다.)

+0

좋은데,'subproject1.script1_main.py'의 내부에서'common'에 접근하기 위해 무엇을 말할 수 있습니까? 나는'import common'을 시도했으나 에'File "movie/main.py"를 받았습니다. import importError : common이라는 모듈이 없습니다'나는 sys.path'를 수동으로 설정하고 싶지 않습니다. 내가 놓친 게 있니? –

+0

'import .. common '이 작동해야한다고 생각합니다. 하위 프로젝트 파일을 직접 실행하지 말고 최상위 레벨에서 스크립트를 실행하고 있는지 확인하십시오. 그렇지 않으면 패키지에 있음을 알지 못할 수도 있습니다 (가져 오기의'..' 부분에 대한 오류가 발생합니다). 케이스). – Blckknght

+1

1. "common"디렉토리는 내부에'__init __. py' 파일이 필요합니다. 2.'import .. common '명령은'from .. import common'명령이 맞습니다. projectroot에는'__init __. py'도 포함되어 있어야하며 부모 패키지처럼 가져올 수 있어야합니다. 3. projectroot를 가져 오지 않고 스크립트를 실행하면 'import common'을 쉽게 할 수 있습니다. 왜냐하면 '.' 시작시 파이썬 경로에 스크립트의 디렉토리가 자동으로 추가됩니다. – hynekcer

0

내 기본 설정은 별도의 "bin"또는 "scripts"입니다. 라이브러리/패키지 등의 하위 프로젝트와 디렉토리 : 스크립트가 각 평소 패키지 필요한 모든 하위 프로젝트를 참조 할 수있는

projectroot 
    | 
    |- scripts 
    | 
    |- lib 
    | | 
    | `- matcher.py 
    | `- merger.py 
    | `- subproject1 
    | `- subproject2 
    | `- subproject3 

아이디어. 또한 하위 프로젝트는 가져 오기를 통해 서로를 참조 할 수 있습니다.

그런 다음 도움이 될 경우 하위 프로젝트 패키지를 설정하는 기본 또는 공유 스크립트를 사용할 수도 있습니다.

+0

나는 그 부서를 좋아하지만 나는 각자의 스크립트를 별도의 하위 프로젝트에 넣어야하는 이유를 보여주기 위해 나의 대답을 편집했다. 왜냐하면 각 "스크립트"에는 여러 부분이 있기 때문이다. 각기 다른 하위 프로젝트에서 사용할 수있는 공유 라이브러리 코드 - 함수 (및 클래스)를 갖고 싶습니다. –

+0

공유 코드는 libs의 루트에 있어야한다고 생각합니다. 내 편집을 참조하십시오. –

+1

Matt -'scripts' 아래의 스크립트에서'lib'로부터 어떻게 가져올 것이 있습니까? 상대적으로 가져 오기는 기술적으로 모듈이 아니기 때문에 사용할 수 없습니다. –

0

Please use setuptools가 배포하는 두 스크립트 라이브러리 :

예를 들어, 당신이 라이브러리를 모든 사용자 코드를 작성할 수 있습니다, 당신의 진입 점을 가지고 별도의 모듈을 필요로하지 않는 경우

from setuptools import setup 

setup(
    # other arguments here... (e.g. packages/package_dir) 
    entry_points = { 
     'console_scripts': [ 
      'script1 = subproject1.script1:main', 
      'script2 = subproject2.script2:main', 
     ], 
    } 
) 

다음이 당신을위한 도구입니다. 스크립트가 있다면 괜찮아요.하지만 main 함수를 참조 할 수 있어야합니다. (위의 예제 참조)