Cx_Freezing PySide,praw,请求应用程序在冻结时停止工作

Posted

技术标签:

【中文标题】Cx_Freezing PySide,praw,请求应用程序在冻结时停止工作【英文标题】:Cx_Freezing a PySide, praw, requests application stops working when frozen 【发布时间】:2015-12-06 18:55:13 【问题描述】:

我遇到了 praw、cx_freeze、pyside 和 requests 的问题,在冻结一切正常之前,但是当我冻结这种情况时,我认为 requests 出了问题: http://pastie.org/10614254

这是我正在使用的项目:https://github.com/MrCappuccino/WallDit-QT

这是我的 setup.py:https://gist.github.com/MrCappuccino/0f1b0571d29d47a95895

import sys
import cx_Freeze
import PySide
import praw
import requests.certs
from cx_Freeze import setup, Executable

exe = Executable(
      script="WallDit_QT.py",
      base="Win32GUI",
      targetName="WallDit_QT.exe"
     )

#includefiles = ['README.txt', 'CHANGELOG.txt', 'helpers\uncompress\unRAR.exe', , 'helpers\uncompress\unzip.exe']
#build_exe_options = "packages": ["os"], "includefiles": ['README.txt', 'CHANGELOG.txt']

setup(name = 'WallDit_QT',
  version = '1.0',
  author = 'Disco Dolan',
  description ='Set your wallpaper interactively!',
  executables = [exe],
  options = 'build.exe': "include_files":['cacert.pem', 'praw.ini', 'README.md'],
  requires = ['PySide', 'cx_Freeze', 'praw', 'shutil', 'requests']
)

有人可以帮忙吗?

我已经尝试添加 cacert.pem,但无济于事,此时我没有更多想法

【问题讨论】:

【参考方案1】:

对于某些冻结的应用程序,您必须在冻结的应用程序内设置 cacert(或一般的外部数据)路径。

Setup.py 部分

您首先需要将它包含在您的构建选项中并手动指定安装目录。这是 setup.py 中唯一的部分:

# notice how I say the folder the certificate is installed
"include_files":[(requests.certs.where(),'cacert.pem')]

在您的情况下,这会生成以下设置文件:

import requests
import sys
# more imports

setup(name = 'WallDit_QT',
    version = '1.0',
    author = 'Disco Dolan',
    description ='Set your wallpaper interactively!',
    executables = [exe],
    options = 
        'build.exe': 
            "include_files": [
                (requests.certs.where(),'cacert.pem'), 
                'praw.ini', 
                'README.md'
            ]
        
    ,
    requires = ['PySide', 'cx_Freeze', 'praw', 'shutil', 'requests']
)

应用部分

然后,您需要在运行时在冻结的应用程序中获取证书路径。 对于 PyInstaller,在运行时定义了一个名为 _MEIPASS 的数据目录的路径(可以从 sys._MEIPASS 获取),允许您访问应用程序所需的所有数据。对于 cacert.pem,路径将按如下方式确定:

cacertpath = os.path.join(sys._MEIPASS, "cacert.pem")

对于 cx_Freeze,可以根据安装路径确定路径,并将其与所需数据连接。在这里,我们得到路径如下:

cacertpath = os.path.join(datadir, 'cacert.pem')

您可以通过以下方式轻松获取冻结应用程序的数据目录:

datadir = os.path.dirname(sys.executable)

(请注意,这不适用于非冻结的应用程序,因此为确保它适用于冻结和非冻结的应用程序,Cx_Freeze recommends 您将其编码如下):

def find_data_file(filename):
    if getattr(sys, 'frozen', False):
        # The application is frozen
        datadir = os.path.dirname(sys.executable)
    else:
        # The application is not frozen
        # Change this bit to match where you store your data files:
        datadir = os.path.dirname(__file__)

    return os.path.join(datadir, filename)

然后您将所有请求模块的 GET 和 POST 请求包含在此路径中,如下所示:

request.get(url, headers=headers, verify=cacertpath)

示例 1

示例代码 sn-p 如下:

# load modules
import os
import sys

import requests

# define our path finder


def find_data_file(filename):
    if getattr(sys, 'frozen', False):
        # The application is frozen
        datadir = os.path.dirname(sys.executable)
    else:
        # The application is not frozen
        # Change this bit to match where you store your data files:
        datadir = os.path.dirname(__file__)

    return os.path.join(datadir, filename)


# get our cacert path and post our GET request
cacertpath = find_data_file('cacert.pem')
r = requests.get('https://api.github.com/events', verify=cacertpath)
# print the text from the request
print(r.text)

示例 2

您还可以通过执行以下操作告诉请求将来在哪里可以找到证书:

os.environ["REQUESTS_CA_BUNDLE"] = cacertpath

在这种情况下,我们将执行以下操作。这里的好处是 cacertpath 不需要在每个模块中显式定义(或从另一个模块导入),可以在环境中定义。

import os
import sys

import requests

def find_data_file(filename):
    if getattr(sys, 'frozen', False):
        # The application is frozen
        datadir = os.path.dirname(sys.executable)
    else:
        # The application is not frozen
        # Change this bit to match where you store your data files:
        datadir = os.path.dirname(__file__)

    return os.path.join(datadir, filename)


cacertpath = find_data_file('cacert.pem')
os.environ["REQUESTS_CA_BUNDLE"] = cacertpath

r = requests.get('https://api.github.com/events')
r.text

【讨论】:

我对你的代码块有点困惑,除了最后一个应该放在我的 setup.py 中之外,所有这些都是吗?还有你所说的数据文件是什么意思? 这是否说明了一点? 除了这部分“datadir = os.path.dirname(file)”我什么都懂我怎么知道我的数据文件存储在哪里以及你所说的数据是什么意思文件? __file__ 是未冻结模块的 Python 内置关键字。所以 os.path.dirname(__file__) 给出了当前被解释文件的系统路径。如果应用程序被冻结,__file__ 变量将被删除,但 sys.executable 会为您提供冻结应用程序的路径。 我已经尝试过您的方法,但它似乎仍然无法正常工作,我收到这些错误消息:gist.github.com/MrCappuccino/f081d75ecbaf17a9ec50 updated walldit.py:gist.github.com/MrCappuccino/dc5c25d94fbdd9e13c7e

以上是关于Cx_Freezing PySide,praw,请求应用程序在冻结时停止工作的主要内容,如果未能解决你的问题,请参考以下文章

PRAW - 500 HTTP 响应错误

PRAW:回复帖子

PRAW:将评论和提交对象序列化为 JSON

PRAW:评论提交者的用户名

使用 PRAW 获得 100 多个搜索结果?

帮助获取 Reddit 帖子与 PRAW 链接到的 URL