我想用python的print打开ssh。 以下是我的测试代码。
import subprocess
# case1:
command_str = "\"print(\'test\')\""
# case 2:
# command_str = "\\\"print(\'test\')\\\""
ssh_command = ['ssh', 'USER_X@localhost', 'python', '-c']
ssh_command.append(command_str)
process = subprocess.run(ssh_command, stdout=subprocess.PIPE)
print(process.stdout)
案例1和案例2不起作用。 产出如下,
案例1:
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `python -c print('test')'
b''
案例2:
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `python -c \"print('test')\"'
b''
请告诉我它是如何运作的。
答案 0 :(得分:2)
它应该与
一起使用command_str = "'print(\"test\")'"
或等效
command_str = '\'print("test")\''
最外层的引号和转义是针对本地Python的。因此,在任何一种情况下,本地Python字符串都是'print("test")'
。
本地shell不需要引用或转义,因为subcommand.run(...)
除非shell=True
通过,否则不会调用它。
因此python字符串中的单引号用于远程shell(可能是bash
或其他sh
- 兼容的shell)。传递给远程Python的参数因此是print("test")
。 (并且那里的双引号表示要打印到远程python的字符串文字。)
\
)吗?由于涉及三个级别(本地Python,远程shell,远程Python),我不这么认为。
是的,稍微逃避一下。让我们从后面(或从里到外)构建它。
我们要打印
test
这需要为远程Python进行转义(以形成字符串文字而不是标识符):
"test"
使用print()
功能调用此方法:
print("test")
到目前为止非常熟悉。
现在我们希望将此作为python -c
的参数传递给sh
- 就像shell一样。为了保护(
和)
被解释,我们引用了整个事情。对于已经存在的"
不要终止引用,我们将它们转义:
"print(\"test\")"
您可以在终端中尝试:
$> echo "print(\"test\")"
print("test")
完美!
现在我们必须在(本地)Python中表示整个事物。我们在它周围包含另一层引号,必须转义四个(!)现有的引号以及两个反斜杠:
"\"print(\\\"test\\\")\""
(完成。这也可以用作command_str
。)
'
)和转义吗?我不知道,但至少不那么容易。为什么?因为除了Python之外,双引号和单引号不能与sh
和bash
互换:在单引号内,这些shell假定原始字符串而不转义直到结束'
发生。
如果字面上看,去看医生。如果比喻,是的,我也是。当你的代码未来的读者(包括你自己)试图解开那个引用逃避的森林时,他们可能会有同样的感受。
但我们心爱的Python标准库中有painless alternative!
import shlex
command_str = shlex.quote('print("test")')
这更容易理解。内部引号(这里是双引号,但实际上并不重要:shlex.quote("print('test')")
工作得很好)适用于远程Python。外部引号显然适用于本地Python。除了远程shell之外的所有引用和转义都由此实用程序函数处理。
答案 1 :(得分:-1)