首页 > 解决方案 > 为什么这个 Django 视图无法通过 subprocess.call 运行 Powershell 脚本?

问题描述

以下tests.py正常工作并通过subprocess.call执行 Powershell 脚本:

import subprocess

subprocess.call(["C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", ". \"./testers.ps1\";", "&Foo(10)"])

尝试从 Django/REST 视图中执行相同的调用,但未能这样做:

import subprocess

from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view

@api_view(['POST'])
def bar(request):
    if request.method == 'POST':
        subprocess.call([f"C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", ". \"./testers.ps1\";", "&Foo({request.data})"])

        return Response(request.data, status=status.HTTP_201_CREATED)
    else:
        return Response(request.errors, status=status.HTTP_400_BAD_REQUEST)

错误:

[09/Jul/2021 08:31:52] "POST /profile-eraser/ HTTP/1.1" 201 5646
. : The term './testers.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:3
+ . "./testers.ps1"; &Foo({request.data})
+   ~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (./testers.ps1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

& : The term 'Foo' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:21
+ . "./testers.ps1"; &Foo({request.data})
+                     ~~~~~
    + CategoryInfo          : ObjectNotFound: (hello:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

PS脚本:

Function Foo($intIN)
{
    Write-Host ($intIN + 1)
}

Write-Host "PowerShell sample says hello."

为什么我可以从 tests.py 运行它,但不能从 Django 视图中运行它?我执行此操作的最佳方法是什么?

标签: pythondjangopowershell

解决方案


正如@Santiago Squarzon 指出的那样,我必须将绝对路径传递给脚本文件。关于第二个错误,我忘记指出 subprocess.call 的最后一个值的 f 字符串

工作代码现在看起来像这样:

@api_view(['POST'])
def bar(request):
    if request.method == 'POST':
        subprocess.call([f"C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", ". \"C:\\Users\\me\\./testers.ps1\";", f"&hello({request.data})"])

        return Response(request.data, status=status.HTTP_201_CREATED)
    else:
        return Response(request.errors, status=status.HTTP_400_BAD_REQUEST)

推荐阅读