2017-12-22 17 views
0

일부 인수로 쉘 스크립트를 호출하는 Flask 애플리케이션 (Linux, mod_wsgi, Python 3이있는 Apache)이 있습니다. subprocess.run() 명령 인수에 비 ASCII 문자가있는 경우 오류를 다음하면 응용 프로그램에서 발생합니다subprocess.run() 인수 인코딩

'ascii' codec can't encode characters in position 5-6: ordinal not in range(128)

내가 그것을 해결하기 위해 노력 많은 시간을 보냈다.

명령 줄에는 문제가 존재하지 않으며 응용 프로그램에만 있습니다.

전체 응용 프로그램의 출력이 유니 코드이며 문제가 없습니다. 몇 가지 연구가 끝난 후에 나는 문제가 "파일 시스템 인코딩"에 있다고 결론을 내렸다.

run.wsgi 스크립트에 일부 로깅 구문을 추가했습니다. FS 인코딩은 실제로 'ascii'(그리고 명령 행에서 'utf-8')입니다.

다음 단계에서 나는 아파치 서버가 환경에서 LANG=C 시작했다이 문서 How to change file system encoding via python?

을 발견했다. /etc/sysconfig/httpd에 경고가 있음에도 불구하고 C.UTF-8으로 변경했습니다. 그게 도움이 안된다, FS 인코딩은 여전히 ​​'ascii'이었다. 나는 심지어 sys.getfilesystemencoding()에서 lambda: 'utf-8'까지 원숭이 패치를했다. 그러나 오류는 여전히 존재합니다.

변경 될 때마다 제대로 httpd 서비스를 다시 시작했습니다.

나는 재치가있다.

  1. 내 문제는 실제로 FS 인코딩 때문입니까?
  2. 그렇다면 utf-8로 바꾸려는 시도가 실패한 이유는 무엇입니까?
  3. 가장 중요한 점은이 문제를 어떻게 해결할 수 있습니까?

갱신 1 :

코드 : mod_wsgi에의 맥락에서

import subprocess as sub 
    cmdresult = sub.run(
     [SCRIPT, tid, days, name], 
     stdin=sub.DEVNULL, stdout=sub.PIPE, stderr=sub.DEVNULL, 
     encoding='ascii', # 'utf-8' will not help, this affects stdin, stdout I/O only 
     check=True) 
+1

'shell = True'를 사용하여 호출합니까? 인수를 문자열이나 목록으로 전달하고 있습니까? 'subprocess' 모듈을 사용하는 실제 코드를 보여주십시오. –

+0

OS 레벨에서'exec()'와 친구들은 하위 프로세스에 전달한 인수에 어떤 인코딩을 사용했는지 상관하지 않습니다. POSIX는 C'char *'문자열로 표현할 수 있어야하며, 서브 프로세스로 보내어 디코딩합니다. –

+0

@DanielPryden 코드가 추가되었습니다. 기본적으로'shell = False'입니다. – VPfB

답변

0

, 당신은 mod_wsgi에 데몬 모드를 사용하고 있는지 확인하고 mod_wsgi에 데몬 프로세스 그룹에 대한 LANG/로케일을 설정해야합니다. 여기에 반복 너무 많이 훨씬 더 자세한 설명은 다음을 참조하십시오

+0

며칠 전에 데몬 모드에 대한 블로그를 읽었으며 임베디드의 변경 사항을 내 목록의 데몬 모드로 높게 변경했습니다. 이 블로그를 작성해 주셔서 감사합니다. 이 문제에 대해서는'mod_wsgi'와 관련이 거의 없다고 생각합니다. 파이썬 솔루션을 찾았습니다. – VPfB

0

내가 짧은 테스트를했다 (이것은 다른 사람에게 도움이 될 수 있기를 바랬 자신의 질문에 대답) 프로그램. 이것이 내가 찾은 것입니다 :

  1. 파일 시스템 인코딩이 핵심입니다.
  2. 원숭이 패치가 작동하지 않습니다. 글쎄, 괜찮아. 어쨌든 해결책으로 받아 들일 수는 없습니다.
  3. LANG=C.UTF-8은 로케일이 설치되어 있고 내 시스템에 없었습니다 (locale -a으로 확인). 그러나 사용 가능한 두 번째 시스템에서 작동했습니다.

    cmdresult = sub.run(
        [SCRIPT, tid, days, name.encode('utf-8')], 
        ... 
    

이 작동하지만 하나 개의 질문이 remianed :

은이 문서를 준수합니까 내가 인코딩을 명시 적으로 확인하고 인수 중 하나로 바이트를 전달할 수
  • ?

    args should be a sequence of program arguments or else a single string

    그리고 하나의 문자열 또는 문자열 목록으로 이해했지만 실제로는 어떤 유형의 목록을 지정하지 않습니다

    내가 찾을 수있는 모든이다. 나는 또한 무엇이 일어날 지 알기 위해 int와 int를 넘어 섰다.

    expected str, bytes or os.PathLike object

    그래서 내 솔루션 괜찮을 것 같다 :이 오류가 발생했습니다.