2017-12-22 7 views
0

私はいくつかの引数を持つシェルスクリプトを呼び出すFlaskアプリケーション(Linux、mod_wsgi、Python 3を持つApache)を持っています。非ASCII文字がsubprocess.run()コマンドの引数である場合、次のエラーがアプリケーションで発生します。subprocess.run()引数のエンコーディング

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

私はそれを修正しようとしている多くの時間を費やしました。

このような問題はコマンドラインには存在せず、アプリケーション内にのみ存在します。

アプリケーション全体の出力はUnicodeであり、問​​題はありません。いくつかの研究の後、私は結論に至りました。問題は "ファイルシステムエンコーディング"です。

run.wsgiスクリプトにいくつかのロギングステートメントを追加しました。 FSエンコーディングは実際には 'ascii'(コマンドラインでは 'utf-8')でした。

は、次のステップでは、私は、Apacheのhttpdサーバがその環境で 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. 最も重要な点:この問題を解決するにはどうすればよいですか?

UPDATE1:

コードスニペット:の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は '' char * '文字列として表現できることを要求します。それらをデコードするサブプロセスに渡します。 –

+0

@DanielPrydenコードが追加されました。デフォルトでは 'shell = False'です。 – VPfB

答えて

0

、あなたがmod_wsgiをデーモンモードを使用していることを確認し、mod_wsgiをデーモンプロセスグループのためにLANG /ロケールを設定する必要があります。ここで繰り返すことが多すぎるより詳細な説明については、以下を参照してください。

+0

私はちょうど数日前にデーモンモードに関するあなたのブログを読んで、埋め込みからの変更をデーモンモードの上に置いてリストに入れました。これらのブログを作成していただきありがとうございます。この問題に関しては、 'mod_wsgi'との接続はほとんどないと思います。私はPythonソリューションを見つけました。 – VPfB

0

を(それが他の人に参考になっ可能性が望んで自分の質問に答える)私は短いテストを行いましたプログラム。これは私が見つけたものです:

  1. ファイルシステムのエンコードが重要です。
  2. モンキーパッチが動作しません。まあ、それはOKです。とにかく解決策として受け入れられません。
  3. LANG=C.UTF-8はロケールがインストールされている必要があり、私のシステムにはありませんでした(locale -aでチェック)。しかし、それが利用可能だった第2のシステムでは、それは働いた。私は明示的にエンコーディングを作成し、引数の一つとしてバイトを渡すことができ
  4. cmdresult = sub.run(
        [SCRIPT, tid, days, name.encode('utf-8')], 
        ... 
    

これは動作しますが、一つの質問がremianed:

それはドキュメントに準拠していますか?

私は見つけることができるすべては、次のとおりです。

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

そして、私は1つの文字列または文字列のリストとしてそれを理解しなかったが、実際にはどのようなタイプのリストを指定していません。私はまた何が起こるかを知るために渡しました。私はこのエラーを得た:

expected str, bytes or os.PathLike object

だから私のソリューションは大丈夫のようです。

関連する問題