Domanda

Voglio ottenere screenshot di una pagina web in Python. Per questo sto usando http://github.com/AdamN/python-webkit2png/ .

    newArgs = ["xvfb-run", "--server-args=-screen 0, 640x480x24", sys.argv[0]]
    for i in range(1, len(sys.argv)):
        if sys.argv[i] not in ["-x", "--xvfb"]:
            newArgs.append(sys.argv[i])
    logging.debug("Executing %s" % " ".join(newArgs))
    os.execvp(newArgs[0], newArgs)

In sostanza chiamate Xvfb-run con i args corretti. Ma man xvfb dice:

Note that the demo X clients used in the above examples will not exit on their own, so they will have to be killed before xvfb-run will exit.

Quindi questo significa che questo script se tutta questa faccenda è in un ciclo, (per ottenere screenshot multipli) a meno che il server X viene ucciso. Come posso fare ciò?

È stato utile?

Soluzione

La documentazione per os.execvp afferma:

  

Queste funzioni tutti eseguono una nuova   programma, sostituendo l'attuale   processi; non restituiscono. [..]

Così, dopo aver chiamato os.execvp nessun altra dichiarazione nel programma verrà eseguito. Si consiglia di utilizzare subprocess.Popen invece:

  

Il modulo subprocess permette di   di spawn nuovi processi, si collegano a loro   ingresso / uscita / conduttori di errore, ed ottenere   i loro codici di ritorno. Questo modulo   intende sostituire molti altri,   moduli e funzioni più anziani, come ad esempio:

Utilizzando subprocess.Popen, il codice per eseguire xlogo nel server framebuffer X virtuale diventa:

import subprocess
xvfb_args = ['xvfb-run', '--server-args=-screen 0, 640x480x24', 'xlogo']
process = subprocess.Popen(xvfb_args)

Ora il problema è che xvfb-run lancia Xvfb in un processo in background. Chiamando process.kill() non ucciderà Xvfb (almeno non sulla mia macchina ...). Sono stato trafficando con questo un po ', e finora l'unica cosa che funziona per me è:

import os
import signal
import subprocess

SERVER_NUM = 99  # 99 is the default used by xvfb-run; you can leave this out.

xvfb_args = ['xvfb-run', '--server-num=%d' % SERVER_NUM,
             '--server-args=-screen 0, 640x480x24', 'xlogo']
subprocess.Popen(xvfb_args)

# ... do whatever you want to do here...

pid = int(open('/tmp/.X%s-lock' % SERVER_NUM).read().strip())
os.kill(pid, signal.SIGINT)

Quindi, questo codice legge l'ID del processo di Xvfb da /tmp/.X99-lock e invia il processo di un interrupt. Funziona, ma non produrrà un messaggio di errore ogni tanto (suppongo si può ignorare, però). Speriamo che qualcun altro in grado di fornire una soluzione più elegante. Cin cin.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top