【问题标题】:Display Python script warnings in a VS C++ code在 VS C++ 代码中显示 Python 脚本警告
【发布时间】:2018-04-12 09:49:57
【问题描述】:

我编写了一个 Python 脚本,它是在 Visual Studio 2013 上编写的大型 C++ 程序的扩展。这些脚本在程序上运行良好,我可以使用system() 命令在项目中轻松调用它。然而,我的新任务是将该脚本中的任何警告显示为 VS 项目 中的警告。我没有共享目录,python 脚本不需要项目中的 C++ 变量,并且脚本没有返回变量。

我目前运行脚本的简单方式:

system("py C:\\Task4\\testing_functions.py");

我尝试使用<python.h> 库,但无法在不篡改配置选项和目录的情况下使其在预先存在的项目上工作,这对公司的其他人来说是不行的。有没有办法可以将 python 日志导出到 Visual Studio 可以读取和显示的报告中?

【问题讨论】:

  • @kabanus 转到该链接,我在另一个链接中找到了他们答案的更好版本:stackoverflow.com/questions/478898/…。虽然这很简洁,但我在我的链接“请注意,这只会获取标准输出而不是标准错误。- kalaxy”中引用了对顶部答案的第一条评论。但是 stderr 是警告和错误所在。使用 popen 并将输出分配给字符串是不够的,文本文件也不够,因为我需要一些 C++ 可以稍后拾取并嵌入到警告和错误日志中。
  • 嗯,那么将system 调用中的stderr 重定向到您选择的文件还不够吗?
  • @kabanus 也许我会这样做,将 stderr 写入文件,将其作为字符串读取,然后手动写入我的用户警告。我对 C++ system 命令不是很熟悉,因为 system("py C:\\Task4\\testing_functions.py > *some out file*"); 写入标准输出如何提示标准错误仅输出?
  • @kabanus 我找到了一个很好(足够*)的解决方案,我会发布它。

标签: python c++ warnings


【解决方案1】:
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <array>

#include <windows.h>
#include <cstdint>
#include <deque>
#include <thread>

using namespace std;

int SystemCapture(
    string         CmdLine,    //Command Line
    string         CmdRunDir,  //set to '.' for current directory
    string&        ListStdOut, //Return List of StdOut
    string&        ListStdErr, //Return List of StdErr
    uint32_t&      RetCode)    //Return Exit Code
{
    int                  Success;
    SECURITY_ATTRIBUTES  security_attributes;
    HANDLE               stdout_rd = INVALID_HANDLE_VALUE;
    HANDLE               stdout_wr = INVALID_HANDLE_VALUE;
    HANDLE               stderr_rd = INVALID_HANDLE_VALUE;
    HANDLE               stderr_wr = INVALID_HANDLE_VALUE;
    PROCESS_INFORMATION  process_info;
    STARTUPINFO          startup_info;
    thread               stdout_thread;
    thread               stderr_thread;

    security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
    security_attributes.bInheritHandle = TRUE;
    security_attributes.lpSecurityDescriptor = nullptr;

    if (!CreatePipe(&stdout_rd, &stdout_wr, &security_attributes, 0) ||
        !SetHandleInformation(stdout_rd, HANDLE_FLAG_INHERIT, 0)) {
        return -1;
    }

    if (!CreatePipe(&stderr_rd, &stderr_wr, &security_attributes, 0) ||
        !SetHandleInformation(stderr_rd, HANDLE_FLAG_INHERIT, 0)) {
        if (stdout_rd != INVALID_HANDLE_VALUE) CloseHandle(stdout_rd);
        if (stdout_wr != INVALID_HANDLE_VALUE) CloseHandle(stdout_wr);
        return -2;
    }

    ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&startup_info, sizeof(STARTUPINFO));

    startup_info.cb = sizeof(STARTUPINFO);
    startup_info.hStdInput = 0;
    startup_info.hStdOutput = stdout_wr;
    startup_info.hStdError = stderr_wr;

    if (stdout_rd || stderr_rd)
        startup_info.dwFlags |= STARTF_USESTDHANDLES;

    // Make a copy because CreateProcess needs to modify string buffer
    char      CmdLineStr[MAX_PATH];
    strncpy_s(CmdLineStr, CmdLine.c_str(), MAX_PATH);
    CmdLineStr[MAX_PATH - 1] = 0;

    Success = CreateProcess(
        nullptr,
        CmdLineStr,
        nullptr,
        nullptr,
        TRUE,
        0,
        nullptr,
        CmdRunDir.c_str(),
        &startup_info,
        &process_info
        );
    CloseHandle(stdout_wr);
    CloseHandle(stderr_wr);

    if (!Success) {
        CloseHandle(process_info.hProcess);
        CloseHandle(process_info.hThread);
        CloseHandle(stdout_rd);
        CloseHandle(stderr_rd);
        return -4;
    }
    else {
        CloseHandle(process_info.hThread);
    }
    /*
    if (stdout_rd) {
        stdout_thread = thread([&]() {
            DWORD  n;
            const size_t bufsize = 1000;
            char         buffer[bufsize];
            for (;;) {
                n = 0;
                int Success = ReadFile(
                    stdout_rd,
                    buffer,
                    (DWORD)bufsize,
                    &n,
                    nullptr
                    );
                printf("STDERR: Success:%d n:%d\n", Success, (int)n);
                if (!Success || n == 0)
                    break;
                string s(buffer, n);
                printf("STDOUT:(%s)\n", s.c_str());
                ListStdOut += s;
            }
            printf("STDOUT:BREAK!\n");
        });
    }
    */
    if (stderr_rd) {
        stderr_thread = thread([&]() {
            DWORD        n;
            const size_t bufsize = 1000;
            char         buffer[bufsize];
            for (;;) {
                n = 0;
                int Success = ReadFile(
                    stderr_rd,
                    buffer,
                    (DWORD)bufsize,
                    &n,
                    nullptr
                    );
                printf("STDERR: Success:%d n:%d\n", Success, (int)n);
                if (!Success || n == 0)
                    break;
                string s(buffer, n);
                printf("STDERR:(%s)\n", s.c_str());
                ListStdOut += s;
            }
            printf("STDERR:BREAK!\n");
        });
    }

    WaitForSingleObject(process_info.hProcess, INFINITE);
    if (!GetExitCodeProcess(process_info.hProcess, (DWORD*)&RetCode))
        RetCode = -1;

    CloseHandle(process_info.hProcess);

    if (stdout_thread.joinable())
        stdout_thread.join();

    if (stderr_thread.joinable())
        stderr_thread.join();

    CloseHandle(stdout_rd);
    CloseHandle(stderr_rd);

    return 0;
}


std::string exec(const char* cmd) {
    std::array<char, 128> buffer;
    std::string result;
    std::shared_ptr<FILE> pipe(_popen(cmd, "r"), _pclose);
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe.get())) {
        if (fgets(buffer.data(), 128, pipe.get()) != nullptr)
            result += buffer.data();
    }
    return result;
}

int main(int argc, char* argv[])
{
    int            rc;
    uint32_t       RetCode;
    string         ListStdOut;
    string         ListStdErr;

    cout << "STARTING.\n";

    rc = SystemCapture(
        "py C:\\Task4\\testing_functions.py",    //Command Line
        ".",                                     //CmdRunDir
        ListStdOut,                              //Return List of StdOut
        ListStdErr,                              //Return List of StdErr
        RetCode                                  //Return Exit Code
        );
    if (rc < 0) {
        cout << "ERROR: SystemCapture\n";
    }

    /*
    cout << "STDOUT:\n";
    cout << ListStdOut;


    cout << "STDERR:\n";
    cout << ListStdErr;

    cout << "Finished.\n";
    */

    cout << "Press Enter to Continue";
    cin.ignore();

    return 0;
}

整个代码将输出包括STDOUTSTDERR 在内的所有内容,我已经注释掉了所有标准输出,因为我只想要警告。

【讨论】:

  • 如果没有人发布更好的内容,请不要忘记在几天内接受您的答案。
  • @kabanus 我该怎么做,我有两个关于堆栈溢出的问题,我在一段时间后回答了自己但从未接受过。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多