为什么生成的字符串包含'\n'
Why does the generated string contain a '\n'
我创建了这个 mre:
import subprocess
m = 'rsync'
url = 'mirror.nsc.liu.se/CentOS/7.8.2003/'
flags = '-avHP --delete '
destf = ''
url_prefix = 'rsync://'
root = '/tmp'
dest = 'test'
cmd = m + ' ' + flags + ' ' + url_prefix+url + ' ' +destf + ' ' + root+'/'+dest
print(cmd)
print(cmd.split(' '))
proc=subprocess.run(cmd.split(' '), capture_output=True)
print(proc.stderr)
这给了我这个输出:
$ python3 test.py
rsync -avHP --delete rsync://mirror.nsc.liu.se/CentOS/7.8.2003/ /tmp/test
['rsync', '-avHP', '--delete', '--bwlimit=800', 'rsync://mirror.nsc.liu.se/CentOS/7.8.2003/', '', '/tmp/test']
b'Unexpected local arg: \nIf arg is a remote file/dir, prefix it with a colon (:).\nrsync error: syntax or usage error (code 1) at main.c(1368) [Receiver=3.1.3]\n'
我真的不明白这里出了什么问题。据我所知,字符串中没有换行符。
如果我把命令行的创建改成这样(去掉destf
),问题依旧:
cmd = '' + m + ' ' + flags + ' ' + url_prefix+url + ' ' + ' ' + root+'/'+dest
但是有了这个(也删除了一个 space)它起作用了:
cmd = '' + m + ' ' + flags + ' ' + url_prefix+url + ' ' + root+'/'+dest
如果我将 ' '
替换为 ' '
,它将再次停止工作。但是当我直接在 shell 中输入字符串时,它甚至可以使用双 spaces.
那么这里到底发生了什么?我可以使用我上面的发现来快速修复鞋拔,但感觉这会在以后困扰我。那么我实际上在这里想念的是什么?我想要 destf
参数的原因是当我使用 wget
时它被设置为 -P
并且可能是另一个命令的其他东西。
它不是在抱怨字符串中的换行符。错误信息有多行,换行符是行与行之间的分隔符。
意外的参数是 '/tmp/test'
之前的空字符串 ''
因为 destf
是空的。
当您使用 .split(' ')
时,多个空格不会合并为一个分隔符。所以当你这样做时
'foo bar'.split(' ')
结果是
['foo', '', 'bar']
而不是
['foo', 'bar']
如果您希望将多个空格合并为一个分隔符,请使用 .split()
而不是 .split(' ')
proc=subprocess.run(cmd.split(), capture_output=True)
感谢 Barmar 提供解决问题的答案。当我出去吃午饭时,我意识到了问题所在。
当一个程序被执行时,它会查找一个传统上称为 argv
的变量,它基本上是一个字符串数组。 shell 通常负责将字符串转换为字符串数组,因此如果调用此命令:
$ foo a b c eee
然后,shell会将字符串解析为:
argv[0] = "foo"
argv[1] = "a"
argv[2] = "b"
argv[3] = "c"
argv[4] = "eee"
但是使用我使用的方法,它最终会变成:
argv[0] = "foo"
argv[1] = "a"
argv[2] = ""
argv[3] = ""
argv[4] = "b"
argv[5] = "c"
argv[6] = ""
argv[7] = ""
argv[8] = ""
argv[9] = "eee"
所以字符串没有问题。问题是绕过 shell 完成的转换。但是使用 .split()
而不是 .split(' ')
解决了它。
我创建了这个 mre:
import subprocess
m = 'rsync'
url = 'mirror.nsc.liu.se/CentOS/7.8.2003/'
flags = '-avHP --delete '
destf = ''
url_prefix = 'rsync://'
root = '/tmp'
dest = 'test'
cmd = m + ' ' + flags + ' ' + url_prefix+url + ' ' +destf + ' ' + root+'/'+dest
print(cmd)
print(cmd.split(' '))
proc=subprocess.run(cmd.split(' '), capture_output=True)
print(proc.stderr)
这给了我这个输出:
$ python3 test.py
rsync -avHP --delete rsync://mirror.nsc.liu.se/CentOS/7.8.2003/ /tmp/test
['rsync', '-avHP', '--delete', '--bwlimit=800', 'rsync://mirror.nsc.liu.se/CentOS/7.8.2003/', '', '/tmp/test']
b'Unexpected local arg: \nIf arg is a remote file/dir, prefix it with a colon (:).\nrsync error: syntax or usage error (code 1) at main.c(1368) [Receiver=3.1.3]\n'
我真的不明白这里出了什么问题。据我所知,字符串中没有换行符。
如果我把命令行的创建改成这样(去掉destf
),问题依旧:
cmd = '' + m + ' ' + flags + ' ' + url_prefix+url + ' ' + ' ' + root+'/'+dest
但是有了这个(也删除了一个 space)它起作用了:
cmd = '' + m + ' ' + flags + ' ' + url_prefix+url + ' ' + root+'/'+dest
如果我将 ' '
替换为 ' '
,它将再次停止工作。但是当我直接在 shell 中输入字符串时,它甚至可以使用双 spaces.
那么这里到底发生了什么?我可以使用我上面的发现来快速修复鞋拔,但感觉这会在以后困扰我。那么我实际上在这里想念的是什么?我想要 destf
参数的原因是当我使用 wget
时它被设置为 -P
并且可能是另一个命令的其他东西。
它不是在抱怨字符串中的换行符。错误信息有多行,换行符是行与行之间的分隔符。
意外的参数是 '/tmp/test'
之前的空字符串 ''
因为 destf
是空的。
当您使用 .split(' ')
时,多个空格不会合并为一个分隔符。所以当你这样做时
'foo bar'.split(' ')
结果是
['foo', '', 'bar']
而不是
['foo', 'bar']
如果您希望将多个空格合并为一个分隔符,请使用 .split()
而不是 .split(' ')
proc=subprocess.run(cmd.split(), capture_output=True)
感谢 Barmar 提供解决问题的答案。当我出去吃午饭时,我意识到了问题所在。
当一个程序被执行时,它会查找一个传统上称为 argv
的变量,它基本上是一个字符串数组。 shell 通常负责将字符串转换为字符串数组,因此如果调用此命令:
$ foo a b c eee
然后,shell会将字符串解析为:
argv[0] = "foo"
argv[1] = "a"
argv[2] = "b"
argv[3] = "c"
argv[4] = "eee"
但是使用我使用的方法,它最终会变成:
argv[0] = "foo"
argv[1] = "a"
argv[2] = ""
argv[3] = ""
argv[4] = "b"
argv[5] = "c"
argv[6] = ""
argv[7] = ""
argv[8] = ""
argv[9] = "eee"
所以字符串没有问题。问题是绕过 shell 完成的转换。但是使用 .split()
而不是 .split(' ')
解决了它。