2

我正在尝试为使用 pywin32 绑定编辑一些 excel 电子表格的程序创建安装程序。我已经使用 py2exe 创建了一个可执行文件,并且在从桌面上的文件夹中运行可执行文件时一切正常。但是,我希望能够分发一个安装程序文件,它将程序安装到 C:\Program Files\ 或任何系统上的等效文件夹中。我也成功了,但是,当使用 pywin32 绑定时,无论工作目录在哪里,它们都会创建临时文件。

这是非常有问题的,因为较新版本的 Windows 已经做到了,因此只有管理员有权写入这些目录。因此,当应用程序从这些目录运行时,它会失败并出现以下错误:

WindowsError: [Error 5] Access is denied: 'C:\\Program Files (x86)\\DataPlotter\\.\\win32com\\gen_py\
\00020813-0000-0000-C000-000000000046x0x1x6'

将应用程序更改为以管理员权限运行是一个糟糕的解决方案,因为它可能会引入漏洞。

是否有人知道此问题的修复方法或如何更改 pywin32 绑定用作临时文件位置的位置。

4

2 回答 2

1

contextlib.contextmanager如果您希望在发生未处理的异常时恢复先前的当前目录,我在对您的回答的评论中描述的关于如何使用装饰器将代码转换为上下文管理器的方式稍微过于简单化了。要做到这一点,还需要在周围添加一个try...finally子句yield(见下文)。

另外,我认为将它作为一个独立的函数而不是某个类的方法以及将要切换到的目录作为参数传递给它会更好——这两者都使它更通用且易于重用。我之所以称它为它pushd()是因为它与 Windows 和 Unix 的同名 shell 命令有相似之处。

from contextlib import contextmanager
import os
import tempfile

@contextmanager
def pushd(dir=None):
    """ Context manager which saves the current working directory before
        changing either to the one passed or the default folder for temporary
        files and then restores the former after the controlled suite of
        statements have executed. This will happened even if an unhandled
        exception occurs within the block. """
    cwd = os.getcwd()
    os.chdir(dir if dir is not None else tempfile.gettempdir())
    try:
        yield
    finally:
        os.chdir(cwd)

# sample usage

with pushd():
    self.xl = win32com.client.gencache.EnsureDispatch("Excel.Application")

做 a 而不是什么都不做也可能很有用,yield cwd这将允许任何可选as变量接收一个指示先前当前工作目录的值,以便在块内进行可能的引用。

于 2012-08-21T17:19:40.730 回答
0

这是一个愚蠢的 hack-y 解决方案,但可以通过在 pywin32 上运行来避免这个问题。

通过将当前工作目录切换到可以安全写入的目录,例如临时目录,可以避免该问题。

#Save the current working directory and then switch back once
#excel has been started. This is so pywin32 does not ruin everything
#by trying to write in the current directory without the proper 
#permission. This mainly happens (for me) when the program is installed in 
#program files which requires administrator permissions to write to.

import os
import tempfile
import win32com.client

cwd = os.getcwd()
tdir =  tempfile.gettempdir()
os.chdir(tdir)
self.xl = win32com.client.gencache.EnsureDispatch("Excel.Application") 
os.chdir(cwd)

注意最后切换回原始工作目录不是必需的,但如果您需要它会起作用(就像我一样)。

martineau 在下面使用上下文管理器提出了一种更强大的方法:

from contextlib import contextmanager

@contextmanager
def tempManager(self):
    cwd = os.getcwd()
    tdir =  tempfile.gettempdir()
    os.chdir(tdir)
    yield
    os.chdir(cwd)

with self.tempManager():
    self.xl = win32com.client.gencache.EnsureDispatch("Excel.Application")
于 2012-08-20T21:12:38.183 回答