Selenium Server als subprocess, stdout leer

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
jgillich
User
Beiträge: 16
Registriert: Donnerstag 15. September 2011, 16:20

Ich versuche gerade den Selenium Server als subprocess laufen zu lassen. Ohne Thread geht es nicht, weil der Server während der gesamten Laufzeit laufen muss. Habe es so versucht:

Code: Alles auswählen

#!/usr/bin/python2
# -*- coding: utf8 -*

import subprocess
import threading
import os

wd = os.getcwd()
server_jar = "java -jar " + wd + "/selenium-server-standalone-2.6.0.jar"

class SeleniumServer(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        retcode = subprocess.Popen(server_jar, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        print retcode.stdout.read()
Das rufe ich dann so auf:

Code: Alles auswählen

    from src import seleniumserver
    sserver = seleniumserver.SeleniumServer()
    sserver.start()
    sserver.join ()
Das scheint auch alles fehlerfrei zu funktionieren. Trotzdem bleibt die Ausgabe leer. Auf der Kommandozeile sieht sie hingegen so aus:

Code: Alles auswählen

$ java -jar selenium-server-standalone-2.6.0.jar 
19.09.2011 13:36:55 org.openqa.grid.selenium.GridLauncher main
INFO: Launching a standalone server
13:36:55.342 INFO - Java: Sun Microsystems Inc. 19.0-b09
13:36:55.343 INFO - OS: Linux 3.0-ARCH amd64
13:36:55.353 INFO - v2.6.0, with Core v2.6.0. Built from revision 13840
13:36:55.452 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
...
Von der Ausgabe brauche ich nur obige Zeile, damit ich weiß wohin ich mich verbinden muss.

Was mache ich falsch?
BlackJack

@jgillich: Vermutlich gibt der Server seine Ausgaben nicht auf seinem `stdout` sondern `stderr` aus. Beides unabhängig zu `PIPE`\n und dann nur eines auslesen ist übrigens keine gute Idee, das kann zu Verklemmungen führen.
jgillich
User
Beiträge: 16
Registriert: Donnerstag 15. September 2011, 16:20

Hmm habe eben stderr und auch communicate() probiert, beides gibt nix aus.

Das mit dem PIPE habe ich aus einem Beispiel übernommen, was wäre da denn die bessere Lösung? :)

/edit

Ok, Problem gelöst. Das passiert, wenn man während dem schreiben eines Beitrags nochmal in der Doku rumliest und eigenen Code abändert, das im Forum aber nur zur hälfte macht. Der obige Code funktioniert nämlich, nur mein eigener nicht. :D Probleme durch reinen Zufall lösen, das ist doch was.

Mit communicate() bekomme ich jetzt die gewollte Ausgabe.

Obige Frage bezüglich der pipe würde mich aber trotzdem noch interessieren?! :)
BlackJack

@jgillich: Wenn Du beides umlenkst und auf dem Terminal ausgaben kommen, dann müsste auch bei einem der beiden Datei-Objekte eine Ausgabe kommen.

Wobei ein `read()` und `comminicate()` natürlich erst zurückkehren, wenn das Programm beendet ist. Tut es das in diesem Fall denn? Ist ja anscheinend ein Server.
Benutzeravatar
ocoal
User
Beiträge: 32
Registriert: Mittwoch 20. Juli 2011, 22:44

Mhm,

das Problem geht in die Richtung, die BlackJack ansprach.

Bei Selenium handelt es sich um einen Server mit einem ApplicationLoop, der den stdout-channel nicht freigibt.

Der Aufruf von .read() führt somit in eine Endlos-Schleife bis der Server beendet wird.

Was aber funktioniert (anstelle von .read()) ist folgendes:

Code: Alles auswählen

...
    def run(self):
        selenium_process = subprocess.Popen(server_jar, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        while True:
            new_line = selenium_process.stdout.readline().strip()
            if new_line:
                print new_line
...
Beste Grüße,
-Colin-
jgillich
User
Beiträge: 16
Registriert: Donnerstag 15. September 2011, 16:20

@Blackjack: Du hast recht. Die Ausgabe kam nur, weil ich den Server nebenher in einer Kommandozeile laufen hatte und er sich deshalb nach der Ausgabe wieder beendet (startet anscheinend nicht 2 mal).

@ocoal: Das funktioniert super. Habe das jetzt so abgeändert, dann bekomme ich die URL die ich wollte:

Code: Alles auswählen

import re
...
        getlines = True
        while getlines:
            new_line = selenium_process.stdout.readline().strip()
            if new_line:
                url = re.search('INFO - RemoteWebDriver instances should connect to: .*', new_line)
                if not url is None:
                    getlines = False
                    
        url = re.search(r'http://.*', url.group())
        print url.group()       
Danke an euch beide. :)
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Schleife würde ich wohl eher so in der Art machen:

Code: Alles auswählen

        url = None
        while url is None:
            line = selenium_process.stdout.readline()
            if not line:
                break
            url = re.search('INFO - RemoteWebDriver instances should connect to: .*', line.strip())
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Man könnte doch auch einfach stdout und stderr überhaupt nicht in einer pipe stecken...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Dann kann man aber auch nicht die IP aus der Ausgabe fischen, was der OP aber machen will. ;-)
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ah, das hatte ich überlesen, sorry...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten