Python - 从互联网下载 .exe 文件

4
在创建我的程序的自动更新器的过程中,我遇到了成功下载.exe文件的困难。
我所做的事情类似于这样:
import urllib

url = '--insert-url--'

f = urllib.urlopen(url)
file = f.read()
f.close
f2 = open('download.exe', 'w')
f2.write(file)
f2.close

我在下载时没有遇到任何错误,但当我尝试运行时,出现以下错误:
“此文件的版本与您正在运行的Windows版本不兼容。检查计算机的系统信息以查看您是否需要程序的x86(32位)或x64(64位)版本,然后联系软件发布者。”
我自己上传执行文件,并且之前也能正常运行。
我还尝试了一些其他下载方法,结果都是同样的错误,并且我也尝试将其上传到不同的网站以确保这不是问题所在。
我需要特别的操作方式吗?
编辑:
我进行了进一步的下载测试。我在另一台电脑上(一台32位系统)运行了程序(现在我正在使用Spencer发布的内容)。我没有在那台电脑上收到错误消息,但当我运行程序时,命令行出现了,因为我正在使用命令行样式的.exe作为我的测试下载,但是闪烁的白色条形输入栏只是在我结束程序之前到处跳动,因此显然某些东西已经损坏了。
此外,下载过程是否可以使用批处理文件完成?这几乎会更容易,因为程序将必须重新启动以开始使用新的更新,因为它将使用全新的.exe。(我将使用py2exe将程序制作成.exe。)

1
由于文件扩展名为'.exe',我假设您正在Windows上进行此操作。尝试将f2文件的模式更改为“'wb'”以以二进制模式写入它。默认情况下是文本模式,会将遇到的所有换行符(字节)更改为回车+换行符。 - martineau
如果您手动下载(通过浏览器访问)并执行它,是否会遇到相同的问题? - Senthil Kumaran
@Senthil 如果我手动下载它,它可以正常工作。 - user631175
3个回答

3

我猜想你需要在调用open时包含b(二进制)标志:

import urllib

url = '--insert-url--'
f = urllib.urlopen(url) file = f.read() f.close() f2 = open('download.exe', 'wb') f2.write(file) f2.close()

此外,你在调用.close()时省略了父级。我不确定这是你理解上的问题还是示例上的问题,但我已在上面的代码中进行了修复。

另外,如果你的.exe文件很大,你可能希望在下载时将其写入文件中(目前你正在将整个文件读入内存)。代码如下:

f2 = open("download.exe", "wb")
try:
    while True:
        data = f.read(4096)
        if not data:
            break
        f2.write(data)
finally:
    f.close()
    f2.close()

很奇怪。你能将下载的 .exe 文件与“正常工作”的 .exe 文件进行比较,看看有什么不同吗?(我不使用 Windows,所以无法推荐 diff 工具...但我相信 Google 会有一些建议) - David Wolever
我使用了WinDiff,它唯一发现的差异是它们具有不同的创建日期。 - user631175
你在使用 diff 程序时要小心,如果它们没有进行二进制比较,可能会给你带来误导。 - Spencer Rathbun
实际上,windiff 不支持二进制比较。 - Winston Ewert
猛击桌面在寻找发布文件链接时,我发现我使用的链接是下载页面的URL而不是文件本身。Spencer和David提供的方法都完美地解决了问题。感谢你们帮我找到我的愚蠢!:D - user631175
显示剩余5条评论

3
根据官方Python urllib文档所述: 如果read()方法中省略或为负的size参数,则有可能无法读取到数据流的末尾,一般情况下也没有很好的方法来确定从套接字读取整个数据流。 这个库中的另一个选择是:
import urllib

url = '--insert-url--' 

filename = 'download.exe'  
urllib.urlretrieve(url, filename)

非常有趣,我之前没有意识到这一点。如果这被证明是解决方案,请在此处评论,以便我能注意到它。 - David Wolever
似乎加快了下载速度,但仍然无法正常工作。 - user631175

0

所以,我认为你可能遇到了不同的问题。

我的规格:Python3.X,通过Homebrew安装。使用Python的urllib.request模块,因为它是当前支持的模块。

我认为你正在下载一个HTML页面,该页面将你重定向到下载链接。如果你试图从链接下载,这种情况尤其常见。许多网站和服务器会让你点击一个按钮,该按钮会提供一个不同的URL来下载。

例如,如果你尝试下载任何Microsoft link,比如FCIV校验程序,下载按钮实际上会通过不同的URL进行路由。


答案

我的建议是,您可以将下载的字节文件以.htm/l文件形式加载。从这里,您可以尝试查找具有应用程序扩展名的url;

例如,如果您坚持使用 FCIV 示例,您将下载一些会导致相同错误的内容:

此文件的版本与您正在运行的Windows版本不兼容。请检查计算机的系统信息,以查看您是否需要程序的x86(32位)或x64(64位)版本,然后联系软件发布者。

经过仔细检查,如果您将此文件作为.htm/l文件加载,您可以搜索x86字符串并发现它在具有实际名称 https://download.microsoft.com/download/c/f/4/cf454ae0-a4bb-4123-8333-a1b6737712f7/Windows-KB841290-x86-ENU.exe 的url上。之后,如果您使用此新的url/https请求尝试在原始位置进行下载,您将获得一个正确的.exe文件。


编辑 对不起,这个答案只适用于2017年的Python3.X版本。这个答案对于6年前提出的原始问题来说有点晚了。此外,关于文件写入中的b标志的其他答案和评论是正确的。该文件应该以wb权限打开。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接