gpt4 book ai didi

python - Windows 上与 Python 共享内存中的信号量?

转载 作者:太空宇宙 更新时间:2023-11-03 14:52:53 27 4
gpt4 key购买 nike

这是场景。我有一个 Python 脚本,它将在运行其主代码之前启动另一个程序(我们称之为 P)。多个Python脚本可以同时运行,但是如果程序P已经启动,则不应再次启动:

pid 100 starts up
pid 100 starts program P with pid n and detaches it
pid 100 runs main
pid 101 starts up
pid 101 does not start program P because it's already started
pid 101 runs main
pid 100 main finishes
pid 100 does not terminate program P because pid 101 needs it
pid 100 terminates
pid 101 main finishes
pid 101 terminates program P with pid n
pid 101 terminates

在 C 中,我可能可以通过 mmap 文件并在其中放入信号量来跟踪它来创建共享内存。一旦信号量达到 0,我也可以终止程序 P。但我不知道如何在 Windows 上的 Python 和 中执行此操作。

我应该如何解决这个问题,即是否有已经建立的方法来解决这个问题?

最佳答案

我创建了一个示例,说明如何使用套接字而不是共享内存信号量在 Windows 上实现此行为。这达到了同样的目的;只要至少有一个 Python 脚本正在运行,C++ 程序就会继续运行。一旦所有脚本完成,只要在一定的超时时间内不再启动Python脚本,C++程序就会完成。

这里的大部分代码都进入 C++ 程序,该程序运行一个线程来监视来自 Python 脚本的 TCP 连接。

Python 脚本只是检查/启动 Windows 程序,然后打开一个套接字,该套接字一直保持打开状态,直到脚本结束。

Windows 程序检测套接字连接和断开连接,从而跟踪 Python 脚本的运行时间。

在这些示例中,Windows 程序恰好称为“ConsoleApplication11.exe”。我使用了端口 1234 和 15 秒的超时,您可以在 c++ 程序的第 19-21 行中更改这些。另外,如果您想让 C++ 程序的终止更加立即,请在 client_monitor_thread() 末尾调用 exit() 而不是 return。

希望这可能有用。

Python 脚本:

import socket
import time
import psutil
import os

# check if the C++ program is running, start it if not
cppProgramName = "ConsoleApplication11.exe"
progRunning = False
for pid in psutil.pids():
p = psutil.Process(pid)
if (cppProgramName in p.name()):
progRunning = True

if not progRunning:
os.startfile(cppProgramName)
time.sleep(5) # wait for c++ program to start

# open a socket to the C++ program to tell it we need it to keep running
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 1234))

# (MAIN PROGRAM)
time.sleep(3)
# (END OF MAIN PROGRAM)

# close the socket to the C++ program
s.close()

C++ 程序:

// ConsoleApplication11.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <iostream>
#include <set>
#include <chrono>
#include <thread>

#include <winsock2.h>
#include <Ws2tcpip.h>

#pragma comment(lib, "ws2_32.lib") // link with Ws2_32.lib


namespace
{
const unsigned int commonPort = 1234; // must match Python app
const unsigned int noClientsTimeoutLimit = 15; // quit when no clients connected for this many seconds
bool clientMonitorRunning = true; // flag to show client monitor is running


void client_monitor_thread()
{
// start up winsock service version 2.2
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
{
std::cout << "WSAStartup() failed with error: " << iResult << std::endl;
clientMonitorRunning = false;
return;
}

// create a socket for listening for incoming connection requests.
SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET)
{
std::cout << "socket() function failed with error: " << WSAGetLastError() << std::endl;
closesocket(listenSocket);
clientMonitorRunning = false;
return;
}

// sockaddr_in structure specifies the address family, IP address, and port for the socket
sockaddr_in service;
service.sin_family = AF_INET;
inet_pton(AF_INET, (PCSTR)"127.0.0.1", &(service.sin_addr));
service.sin_port = htons(commonPort);
if (SOCKET_ERROR == bind(listenSocket, (SOCKADDR *)& service, sizeof(service)))
{
std::cout << "bind function failed with error " << WSAGetLastError() << std::endl;
closesocket(listenSocket);
clientMonitorRunning = false;
return;
}

// Listen for incoming connection requests on the created socket
if (SOCKET_ERROR == listen(listenSocket, SOMAXCONN))
{
wprintf(L"listen function failed with error: %d\n", WSAGetLastError());
closesocket(listenSocket);
clientMonitorRunning = false;
return;
}

std::cout << "Listening on port " << commonPort << std::endl;

// mow monitor client connections
std::set<unsigned int> activefds;
int timeoutCounter = 0;

while (clientMonitorRunning)
{
// check for existing clients disconnected
if (0 != activefds.size())
{
std::set<unsigned int> disconnectedfds;
for (auto fd : activefds)
{
int flags = 0;
char buf[10];
int rv = recv(fd, buf, 10, flags);
if (0 == rv)
{
disconnectedfds.insert(fd);
}
}
for (auto fd : disconnectedfds)
{
activefds.erase(fd);
}
}

// are any clients connected? do we need to quit?
if (0 == activefds.size())
{
std::cout << "No clients - will exit in " << noClientsTimeoutLimit - timeoutCounter << " seconds" << std::endl;
++timeoutCounter;
if (timeoutCounter == noClientsTimeoutLimit)
{
for (auto fd : activefds)
{
closesocket(fd);
}
closesocket(listenSocket);
clientMonitorRunning = false;
return;
}
}
else
{
timeoutCounter = 0;
}

// check for activity on the listening socket
fd_set readfds;
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
FD_ZERO(&readfds);
FD_SET(listenSocket, &readfds);
switch (select(sizeof(readfds), &readfds, NULL, NULL, &timeout))
{
case 0: // timeout
{
break;
}
case SOCKET_ERROR:
{
std::cout << "listen failed with error: " << WSAGetLastError() << std::endl;
closesocket(listenSocket);
clientMonitorRunning = false;
return;
}
default:
{
if (FD_ISSET(listenSocket, &readfds))
{
// accept the connection.
SOCKET fd = accept(listenSocket, NULL, NULL);
if (fd == INVALID_SOCKET)
{
std::cout << "accept failed with error: " << WSAGetLastError() << std::endl;
closesocket(listenSocket);
clientMonitorRunning = false;
return;
}
else
{
unsigned long nonBlock = 1;
ioctlsocket(fd, FIONBIO, &nonBlock);
activefds.insert(fd);
}
}
break;
}
}
}

return;
}
}


int main()
{
// start the client monitor thread, which will run until no clients are connected
std::thread clientMonitor(client_monitor_thread);

// placeholder for doing the actual work in this program
// loop until the client monitor thread exits
while (clientMonitorRunning)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}

// clean up
clientMonitor.join();
WSACleanup();
return 0;
}

关于python - Windows 上与 Python 共享内存中的信号量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45789505/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com