69666


`subprocess` でコマンドを実行しようとしたのですが、うまくいきませんでした。

**実行コマンド:**

[code]

    cmd = 'psql -h hoge.local -p 5432 -d fuga-U fuga-c r"\copy schema.table from '\\hoge\fuga\data.csv' CSV HEADER"'
    
[/code]

の部分で、以下のエラーが出ました。

**エラーメッセージ:**

[code]

    SyntaxError: unexpected character after line continuation character subprocess
    
[/code]

おそらく `r'hogehoge'` でエスケープを回避すればよいと思うのですが、クオートが何重にもなっていてどう対処してよいかわかりません。

詳しい方、お手数ですがよろしくお願いいたします。

**実行環境**  
Windows 10  
Python 3.7


CC BY-SA 4.0
2020-08-18T12:51:03.523
69663
2020-08-18T16:39:17.497
2020-08-18T16:39:17.497
3060
12457
question
python python3 postgresql
subprocess でクォートを含むコマンドの実行時にエラーが発生する


一応エスケープの関係を見直し、`r`を外して以下のようにすれば1個の文字列として成立すると思われます。  
`print(cmd)`は確認のために追加しています。

[code]

    cmd = 'psql -h hoge.local -p 5432 -d fuga-U fuga-c "\\copy schema.table from \'\\\\hoge\\fuga\\data.csv\' CSV HEADER"'
    print(cmd)
    
[/code]

しかし、無理をして1個の文字列に収めようとしなくても良いのでは？  
Pythonドキュメントの以下の記述に抵触するので、使わない方が良いと思われます。

[よく使われる引数](https://docs.python.org/ja/3.7/library/subprocess.html#frequently-
used-arguments)

> 単一の文字列を渡す場合、shell は True でなければなりません
> (以下を参照)。もしくは、その文字列は引数を指定せずに実行される単なるプログラムの名前でなければなりません。

[Popen コンストラクター](https://docs.python.org/ja/3.7/library/subprocess.html#popen-
constructor)

> Windows で shell=True とすると、COMSPEC 環境変数がデフォルトシェルを指定します。Windows で shell=True
> を指定する必要があるのは、実行したいコマンドがシェルに組み込みの場合だけです (例えば dir や
> copy)。バッチファイルやコンソールベースの実行ファイルを実行するために shell=True は必要ありません。

> args はプログラム引数のシーケンスか、単一の文字列でなければなりません。

> 特に明記されない限り、args をシーケンスとして渡すことが推奨されます。

* * *

上記にも引用したとおり、コマンドおよび引数はもちろん1個の文字列で指定出来ますが、文字列のリストで渡す方法もあります。  
リストで渡すならシングルクォーテーションとダブルクォーテーションの組み合わせとか入れ子の関係は緩和されるでしょう。

[subprocess ---
サブプロセス管理](https://docs.python.org/ja/3.7/library/subprocess.html)

> subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None,
> capture_output=False, shell=False, cwd=None, timeout=None, check=False,
> encoding=None, errors=None, text=None, env=None, universal_newlines=None,
> **other_popen_kwargs)  
>  args で指定されたコマンドを実行します。コマンドの完了を待って、CompletedProcess インスタンスを返します。

[args](https://docs.python.org/ja/3.7/library/subprocess.html#subprocess.CompletedProcess.args)

> プロセスを起動するときに使用された引数。1 個のリストか 1 個の文字列になります。

[よく使われる引数](https://docs.python.org/ja/3.7/library/subprocess.html#frequently-
used-arguments)

> args
> はすべての呼び出しに必要で、文字列あるいはプログラム引数のシーケンスでなければなりません。一般に、引数のシーケンスを渡す方が望ましいです。なぜなら、モジュールが必要な引数のエスケープやクオート
> (例えばファイル名中のスペースを許すこと) の面倒を見ることができるためです。

以下のような感じでリストにすれば良いのでは？  
`for ... print(s)`は最初と同様、確認のために追加しています。

[code]

    args = ['psql','-h','hoge.local','-p','5432','-d','fuga-U','fuga-c','"\copy schema.table from \'\\\\hoge\\fuga\\data.csv\' CSV HEADER"']
    for s in args:
        print(s)
    
[/code]

試してみてください。


CC BY-SA 4.0
2020-08-18T15:09:15.210
69666
2020-08-18T15:09:15.210
26370
69663
answer