我正在尝试for通过 python 在 shell 中运行循环。os.popen运行良好,但在 3.x 上已弃用,我想要 stderr。遵循关于如何在 Subprocess.run 命令中使用 for 循环的最高投票答案会导致Syntax error: "do" unexpected,shellcheck 对此表示同意:
for
os.popen
Syntax error: "do" unexpected
import subprocess proc = subprocess.run( "bash for i in {1..3}; do echo ${i}; done", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) print(proc.stderr)
我最终尝试通过 python 调用此 shell 代码https://unix.stackexchange.com/a/611305/362437来重置所有 usb ,因此任何其他方法都将受到赞赏。
您面临的问题是由于您使用subprocess.runshell 命令的方式以及您尝试传递循环的方式所致。Syntax error: "do" unexpected发生这种情况的原因是,您传递的 shell 脚本不包含用于运行循环的正确 shell 语法bash。
subprocess.run
bash
您可以通过确保执行bashshell 并在调用中使用正确的 shell 语法来修复此问题subprocess.run。 应该正确转义内部命令,subprocess.run以便 Python 将其正确传递给 shell。
解决方法如下:
import subprocess # Using subprocess to run a shell command with a for loop proc = subprocess.run( "for i in {1..3}; do echo ${i}; done", # Correct bash syntax for the for loop shell=True, # Run in the shell stdout=subprocess.PIPE, # Capture standard output stderr=subprocess.PIPE, # Capture standard error ) # Print the captured stdout and stderr print("Standard Output:") print(proc.stdout.decode()) # Decode byte output to string print("\nStandard Error:") print(proc.stderr.decode()) # Decode byte error output to string
shell=True
stdout=subprocess.PIPE
stderr=subprocess.PIPE
proc.stdout.decode()
proc.stderr.decode()
for i in {1..3}; do echo ${i}; done
{1..3}
echo ${i}
如果您正在运行 shell 脚本来重置 USB 设备(如您提到的),您可以将其中的命令调整subprocess.run为您需要的任何 Bash 命令。只需确保您传递的命令subprocess.run具有正确的 Bash 语法和任何必要的转义字符即可。
import subprocess # Command to reset USB devices (as per your example) reset_command = """ for device in $(lsusb); do bus=$(echo $device | awk '{print $2}') device_id=$(echo $device | awk '{print $4}' | sed 's/://') echo "Resetting USB device $device_id on bus $bus" sudo usbreset /dev/bus/usb/$bus/$device_id done """ # Run the command using subprocess proc = subprocess.run( reset_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) # Capture and print output print("Standard Output:") print(proc.stdout.decode()) print("\nStandard Error:") print(proc.stderr.decode())
这将运行循环reset_command遍历 USB 设备并用于usbreset重置每个设备的。确保usbreset已安装,并且运行此脚本的用户具有必要的权限(例如,sudo用于设备访问)。
reset_command
usbreset
sudo