0

我正在尝试从 python 运行 PowerShell 脚本以将 .xls 文件转换为 .xlsb。通过循环文件名列表。我遇到命令 3(即 cmd3)的 PowerShell 错误“您不能在空值表达式上调用方法”,我不确定原因(这是我第一次使用 python 并通常运行 PowerShell 脚本)。尝试打开工作簿时遇到错误,但是当直接在 PowerShell 中运行命令时,它似乎工作正常。

代码:

import logging, os, shutil, itertools, time, pyxlsb, subprocess

# convert .xls to .xlsb and / transfer new terminology files
for i in itertools.islice(FileList, 0, 6, None):

    # define extension
    ext = '.xls'

    # define file path
    psPath = f'{downdir}' + f'\{i}'

    # define ps scripts
    def run(cmd):
        completed = subprocess.run(["powershell", "-Command", cmd], capture_output=True)
        return completed
    
    # ps script: open workbook
    cmd1 = "$xlExcel12 = 50"
    cmd2 = "$Excel = New-Object -Com Excel.Application"
    cmd3 = f"$WorkBook = $Excel.Workbooks.Open('{psPath}{ext}')"
    cmd4 = f"$WorkBook.SaveAs('{psPath}{ext}',$xlExcel12,[Type]::Missing, 
           [Type]::Missing,$false,$false,2)"
    cmd5 = "$Excel.Quit()"
    
    # ps script: delete.xls files
    cmd6 = f"Remove-Item '{psPath}{ext}'"
    

    run(cmd1)
    run(cmd2)
    run(cmd3)

    # change extension
    ext = '.xlsb'

    run(cmd4)
    run(cmd5)
    run(cmd6)

    # copy .xlsb files to terminology folder
    shutil.copy(i + ext, termdir)

错误:

Out[79]: CompletedProcess(args=['powershell', '-Command', "$WorkBook = > > $Excel.Workbooks.Open('C:\Users\Username\Downloads\SEND Terminology.xls')"] , returncode=1, stdout=b'', stderr=b"您不能在空值表达式上调用方法。\r\nAt line:1 char:1\r\n+ $WorkBook = $Excel.Workbooks.Open ('C:\Username\User\Downloads\SEND Ter ...\r\n+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n + CategoryInfo : InvalidOperation: (: ) [], RuntimeException\r\n + FullyQualifiedErrorId : InvokeMethodOnNull\r\n \r\n")

任何输入都会有所帮助。

谢谢!

4

1 回答 1

0

问题

正如评论者 vonPryz正确指出的那样,Powershell 命令在单独的进程中运行。进程的内存空间是相互隔离的,当一个进程结束时会被清空。

当您在单独的 Powershell 进程中运行命令时cmd3cmd4cmd5将没有$Excel可用的变量。Powershell 默认$null为不存在变量的值,因此错误消息“您不能在空值表达式上调用方法”。变量也是如此$xlExcel12。这些变量仅在创建它们的进程正在运行时才存在,并且仅在这些进程中可见,即使您设法并行创建了两个进程。

解决方案

命令 cmd1..5 需要在同一个 Powershell 进程中运行,因此每个命令将能够“看到”先前命令创建的变量:

run( cmd1 + ';' + cmd2 + ';' + cmd3 + ';' + cmd4 + ';' + cmd5 )

您将需要更改cmd4为使用另一个变量作为将用​​于保存的扩展名,例如extSave

cmd4 = f"$WorkBook.SaveAs('{psPath}{extSave}',$xlExcel12,[Type]::Missing, 
       [Type]::Missing,$false,$false,2)"    

是完全独立的cmd6,因为它不依赖于 Powershell 变量。它只依赖于 python 变量,这些变量在进程启动之前被解析,因此它仍然可以在单独的进程中运行。

于 2020-12-05T09:34:31.757 回答