Trouble connecting Firefox WebDriver with Selenium in Python - http

i'm running into an error in trying to start up the selenium firefox driver. it seems like others have hit snags at this step, and there is no readily available solution online, so hopefully this question will be broadly helpful. it seems like firefox is failing to establish an http server interface when initiated through selenium's driver. it appears that i can run firefox from the command line with no errors.
i should specify that i am doing this via ssh login to a linux container. i'm running python2.7 on Ubuntu 14.04 LTS (GNU/Linux 3.16.3-elastic x86_64). i have the latest version of selenium (2.44) installed, and i'm using firefox 34.0. i'm using xvfb to spoof a display.
below is my code, the error logs, and some related source code.
from selenium import webdriver
d = webdriver.Firefox()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/firefox/webdriver.py", line 59, in __init__
self.binary, timeout),
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/firefox/extension_connection.py", line 47, in __init__
self.binary.launch_browser(self.profile)
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/firefox/firefox_binary.py", line 66, in launch_browser
self._wait_until_connectable()
File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/firefox/firefox_binary.py", line 105, in _wait_until_connectable
raise WebDriverException("Can't load the profile. Profile "
selenium.common.exceptions.WebDriverException: Message: Can't load the profile. Profile Dir: %s If you specified a log_file in the FirefoxBinary constructor, check it for details.
that error is raised here, due to a timeout:
def _wait_until_connectable(self):
"""Blocks until the extension is connectable in the firefox."""
count = 0
while not utils.is_connectable(self.profile.port):
if self.process.poll() is not None:
# Browser has exited
raise WebDriverException("The browser appears to have exited "
"before we could connect. If you specified a log_file in "
"the FirefoxBinary constructor, check it for details.")
if count == 30:
self.kill()
raise WebDriverException("Can't load the profile. Profile "
"Dir: %s If you specified a log_file in the "
"FirefoxBinary constructor, check it for details.")
count += 1
time.sleep(1)
return True
in the log_file:
tail -f logs/firefox_binary.log
1418661895753 addons.xpi DEBUG checkForChanges
1418661895847 addons.xpi DEBUG No changes found
1418661895853 addons.manager DEBUG Registering shutdown blocker for XPIProvider
1418661895854 addons.manager DEBUG Registering shutdown blocker for LightweightThemeManager
1418661895857 addons.manager DEBUG Registering shutdown blocker for OpenH264Provider
1418661895858 addons.manager DEBUG Registering shutdown blocker for PluginProvider
System JS : ERROR (null):0 - uncaught exception: 2147746065
JavaScript error: file:///tmp/tmplkLsLs/extensions/fxdriver#googlecode.com/components/driver-component.js, line 11507: NS_ERROR_NOT_AVAILABLE: Component is not available'Component is not available' when calling method: [nsIHttpServer::start]
*** Blocklist::_preloadBlocklistFile: blocklist is disabled
1418661908552 addons.manager DEBUG Registering shutdown blocker for <unnamed-provider>
one more point of information. early on, in the firefox driver initalization, socket.bind(('127.0.0.1',0)) was failing with a "can't assign requested address" error. i changed the location to (0.0.0.0,0) and edited the localhost entry in my /etc/hosts, and was able to bind that way. not sure if that could be causing the current failure though.
VV edits per louis's request VV . i specify the two lines where i change the localhost address.
def free_port():
"""
Determines a free port using sockets.
"""
free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
free_socket.bind(('0.0.0.0', 0)) # changed from 127.0.0.1
free_socket.listen(5)
port = free_socket.getsockname()[1]
free_socket.close()
return port
def is_connectable(port):
"""
Tries to connect to the server at port to see if it is running.
:Args:
- port: The port to connect.
"""
try:
socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_.settimeout(1)
socket_.connect(("0.0.0.0", port)) # changed again
socket_.close()
return True
except socket.error:
return False
here's the constructor from webdriver:
def __init__(self, firefox_profile=None, firefox_binary=None, timeout=30,
capabilities=None, proxy=None):
self.binary = firefox_binary
self.profile = firefox_profile
if self.profile is None:
self.profile = FirefoxProfile()
self.profile.native_events_enabled = (
self.NATIVE_EVENTS_ALLOWED and self.profile.native_events_enabled)
if self.binary is None:
self.binary = FirefoxBinary()
if capabilities is None:
capabilities = DesiredCapabilities.FIREFOX
if proxy is not None:
proxy.add_to_capabilities(capabilities)
RemoteWebDriver.__init__(self,
command_executor=ExtensionConnection("127.0.0.1", self.profile,
self.binary, timeout),
desired_capabilities=capabilities,
keep_alive=True)
self._is_remote = False
here's the constructor from extension_connector:
def __init__(self, host, firefox_profile, firefox_binary=None, timeout=30):
self.profile = firefox_profile
self.binary = firefox_binary
HOST = host
if self.binary is None:
self.binary = FirefoxBinary()
if HOST is None:
HOST = "127.0.0.1"
PORT = utils.free_port()
self.profile.port = PORT
self.profile.update_preferences()
self.profile.add_extension()
self.binary.launch_browser(self.profile)
_URL = "http://%s:%d/hub" % (HOST, PORT)
RemoteConnection.__init__(
self, _URL, keep_alive=True)

in posting my edits to louis's comment, i saw that my localhost issue turned up in other locations, as the host is hardcoded in twice more. i had my server master address the issue, changed everything in the source back to 127, and the problem was solved. thanks for prompting me, #louis, and i'm sorry my question wasn't more interesting. will accept my own answer after 2 days when SO allows me.

Related

Micropython uasyncio websocket server

I need to run a websocket server on ESP32 and the official example raises the following exception when I connect from any client:
MPY: soft reboot
Network config: ('192.168.0.200', '255.255.255.0', '192.168.0.1', '8.8.8.8')
b'Sec-WebSocket-Version: 13\r\n'
b'Sec-WebSocket-Key: k5Lr79cZgBQg7irI247FMw==\r\n'
b'Connection: Upgrade\r\n'
b'Upgrade: websocket\r\n'
b'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n'
b'Host: 192.168.0.200\r\n'
b'\r\n'
Finished webrepl handshake
Task exception wasn't retrieved
future: <Task> coro= <generator object 'echo' at 3ffe79b0>
Traceback (most recent call last):
File "uasyncio/core.py", line 1, in run_until_complete
File "main.py", line 22, in echo
File "uasyncio/websocket/server.py", line 60, in WSReader
AttributeError: 'Stream' object has no attribute 'ios'
My micropython firmware and libraries:
Micropython firmware: https://micropython.org/resources/firmware/esp32-idf3-20200902-v1.13.bin
Pip libraries installed: micropython-ulogging, uasyncio.websocket.server
My main.py:
import network
import machine
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.ifconfig(('192.168.0.200', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
if not sta_if.isconnected():
print('connecting to network...')
sta_if.connect('my-ssid', 'my-password')
while not sta_if.isconnected():
machine.idle() # save power while waiting
print('Network config:', sta_if.ifconfig())
# from https://github.com/micropython/micropython-lib/blob/master/uasyncio.websocket.server/example_websock.py
import uasyncio
from uasyncio.websocket.server import WSReader, WSWriter
def echo(reader, writer):
# Consume GET line
yield from reader.readline()
reader = yield from WSReader(reader, writer)
writer = WSWriter(reader, writer)
while 1:
l = yield from reader.read(256)
print(l)
if l == b"\r":
await writer.awrite(b"\r\n")
else:
await writer.awrite(l)
import ulogging as logging
#logging.basicConfig(level=logging.INFO)
logging.basicConfig(level=logging.DEBUG)
loop = uasyncio.get_event_loop()
loop.create_task(uasyncio.start_server(echo, "0.0.0.0", 80))
loop.run_forever()
loop.close()
MicroPython 1.13 implements asyncio v3 which has a number of breaking changes compared to the 3 year old sample referenced.
I suggest you refer to Peter Hinch's excellent documentation on asyncio,
and the asyncio V3 tutorial
I encountered the same problem. I looked at the old implementation of Stream class [1] and the new one [2].
It seems to me, that you need to edit server.py from uasyncio/websocket/.
You can download the files from [3] to your PC. Then at the bottom of the file replace the two instances of "reader.ios" by "reader.s".
Save the file to your ESP32 and it should work. Of course you need to use "from server import WSReader, WSWriter" instead of "from uasyncio.websocket.server import WSReader, WSWriter".
[1] https://github.com/pfalcon/pycopy-lib/blob/master/uasyncio/uasyncio/__init__.py
[2] https://github.com/micropython/micropython/blob/master/extmod/uasyncio/stream.py
[3] https://pypi.org/project/micropython-uasyncio.websocket.server/#files
https://github.com/pfalcon/pycopy-lib/tree/master/uasyncio has a recent (may'21) sample that should also work on standard MicroPython.
or checkout https://awesome-micropython.com under web servers

airflow EmailOperator throws "smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server"?

Trying to use airflow's EmailOperator to send an email on trigger_rule.ONE_FAILED and seeing error:
[2019-10-14 13:31:50,604] {configuration.py:206} WARNING - section/key [smtp/smtp_user] not found in config
Traceback (most recent call last):
File "/bin/airflow", line 27, in <module>
[ args.func(args)
File "/usr/lib/python2.7/site-packages/airflow/bin/cli.py", line 392, in run
pool=args.pool,
File "/usr/lib/python2.7/site-packages/airflow/utils/db.py", line 50, in wrapper
result = func(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/airflow/models.py", line 1493, in _run_raw_task
result = task_copy.execute(context=context)
File "/usr/lib/python2.7/site-packages/airflow/operators/email_operator.py", line 64, in execute
send_email(self.to, self.subject, self.html_content, files=self.files, cc=self.cc, bcc=self.bcc, mime_subtype=self.mime_subtype)
File "/usr/lib/python2.7/site-packages/airflow/utils/email.py", line 44, in send_email
return backend(to, subject, html_content, files=files, dryrun=dryrun, cc=cc, bcc=bcc, mime_subtype=mime_subtype)
File "/usr/lib/python2.7/site-packages/airflow/utils/email.py", line 87, in send_email_smtp
send_MIME_email(SMTP_MAIL_FROM, recipients, msg, dryrun)
File "/usr/lib/python2.7/site-packages/airflow/utils/email.py", line 109, in send_MIME_email
s.starttls()
File "/usr/lib64/python2.7/smtplib.py", line 643, in starttls
raise SMTPException("STARTTLS extension not supported by server.")
smtplib.SMTPException: STARTTLS
Have not changed the default airflow.cfg (other than for basic password authentication to access the webserver) and the email portion looks like
[email]
email_backend = airflow.utils.email.send_email_smtp
[smtp]
# If you want airflow to send emails on retries, failure, and you want to use
# the airflow.utils.email.send_email_smtp function, you have to configure an
# smtp server here
smtp_host = localhost
smtp_starttls = True
smtp_ssl = False
# Uncomment and set the user/pass settings if you want to use SMTP AUTH
# smtp_user = airflow
# smtp_password = airflow
smtp_port = 25
smtp_mail_from = airflow#example.com
Checking the port in the cfg file, it seems to be open and listening...
[rvillanueva#mapr001 queensetl_airflow]$ netstat -plnt | grep ':25'
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN -
tcp6 0 0 ::1:25 :::* LISTEN -
... and I am able to use the linux sendmail bash command for other process that run on this same machine (CentOS 7).
Anyone know what could be going on here or any further debugging tips?
After help from the airflow users mailing list and from the error trace shown above, the thing that fixed this problem was just setting smtp_starttls = False.
Testing with a script like...
# Import smtplib for the actual sending function
import smtplib
from email.mime.text import MIMEText
send_to = 'myaddress#co.org'
msg = MIMEText('Hello World')
msg['Subject'] = 'Test Airflow Email'
msg['From'] = 'airflow#example.com'
msg['To'] = send_to
# SMTP Send
s = smtplib.SMTP('localhost')
s.starttls() # Try commenting out this line and see if you get a different error
s.sendmail(me, [send_to], msg.as_string())
s.quit()
saw the same error and was able to get rid of it by commenting out the s.starttls() line. So now my airflow.cfg file looks like...
[smtp]
# If you want airflow to send emails on retries, failure, and you want to use
# the airflow.utils.email.send_email_smtp function, you have to configure an
# smtp server here
smtp_host = localhost
#smtp_starttls = True
smtp_starttls = False
smtp_ssl = False
# Uncomment and set the user/pass settings if you want to use SMTP AUTH
# smtp_user = airflow
# smtp_password = airflow
smtp_port = 25
smtp_mail_from = airflow#example.com
and email alerts appear to be working fine.

python telegram bot, "socket.error: [Errno 98] Address already in use"

Im developing a telegram bot with this api and I tried to use its webhook example to set up my own bot with webhook method.
I have an Ubuntu server and I have set up nginx on it.
now when trying to run my python bot, I get this error:
Traceback (most recent call last):
File "bot.py", line 106, in <module>
router.run(host=WEBHOOK_LISTEN, port=int(WEBHOOK_PORT), ssl_context= (WEBHOOK_SSL_CERT, WEBHOOK_PRIV_CERT), debug=True)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 841, in run
run_simple(host, port, self, **options)
File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 720, in run_simple
s.bind((hostname, port))
File "/usr/lib/python2.7/socket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 98] Address already in use
so I checked what is using my port 443 and the process is nginx:
root 30734 1 0 Aug21 ? 00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
I can't turn off nginx because my website is on it, and I need the port to set up telegram bot.
EDIT: I will put my code here for more clarification:
WEBHOOK_HOST = 'mywebsite.com'
WEBHOOK_PORT = '8443'
WEBHOOK_LISTEN = '0.0.0.0'
WEBHOOK_SSL_CERT = "/etc/letsencrypt/live/mywebsite.com/cert.pem"
WEBHOOK_PRIV_CERT = "/etc/letsencrypt/live/mywebsite.com/privkey.pem"
WEBHOOK_URL_BASE = "https://%s:%s" % (WEBHOOK_HOST, WEBHOOK_PORT)
WEBHOOK_URL_PATH = "/%s/" % (TOKEN.get_token())
router = flask.Flask(__name__)
#router.route('/', methods=['GET', 'HEAD'])
def index():
return 'OK'
#router.route(WEBHOOK_URL_PATH, methods=['POST'])
def webhook():
if flask.request.headers.get('content-type') == 'application/json':
json_string = flask.request.json
print json_string["message"]["text"] # here I get the text of message
return ''
else:
flask.abort(403)
bot.remove_webhook()
time.sleep(3)
bot.set_webhook(url=WEBHOOK_URL_BASE+WEBHOOK_URL_PATH,certificate=open(WEBHOOK_SSL_CERT, 'r'))
router.run(host=WEBHOOK_LISTEN, port=int(WEBHOOK_PORT), ssl_context=(WEBHOOK_SSL_CERT, WEBHOOK_PRIV_CERT), debug=True)

Python3 daemon library

I'm learning Python3, especially the daemon library. I want my daemon to be called with two possible arguments : start & stop.
So far I have this code :
def start():
with context:
pidfile = open(Config.WDIR+scriptname+".pid",'w')
pidfile.write(str(getpid()))
pidfile.close()
feed_the_db()
def stop(pid):
try:
kill(int(pid),15)
except ProcessLookupError:
print("Nothing to kill… (No process with PID "+pid+")")
if __name__ == "__main__":
scriptname = sys.argv[0]
context = daemon.DaemonContext(
working_directory=Config.WDIR,
pidfile=lockfile.FileLock(Config.WDIR+scriptname),
stdout=sys.stdout,
stderr=sys.stderr)
try:
if sys.argv[1] == 'start':
start()
elif sys.argv[1] == 'stop':
try:
pidfile = open(Config.WDIR+scriptname+".pid",'r')
pid = pidfile.read()
pidfile.close()
remove(name+".pid")
print(name+" (PID "+pid+")")
stop(pid)
except FileNotFoundError:
print("Nothing to kill… ("+scriptname+".pid not found)")
else:
print("\nUnknown option : "+sys.argv[1]+"\n\nUsage "+sys.argv[0]+" <start|stop>\n")
except IndexError:
print("\nUsage "+sys.argv[0]+" <start|stop>\n")
It's working but I wonder if I'm doing it the right way.
In particular, why do I have to manually store the PID. Why is it not already contained in the automatically created file :
myhostname-a6982700.3392-7990643415029806679
or the lock file ?
I think you are mixing up the daemon script and the code responsible for managing it.
Usually in say Ubuntu for example you would control this via upstart
description "Some Description"
author "your#email-address.com"
start on runlevel [2345]
stop on runlevel [!2345]
exec /path/to/script
The actual running python application would never need to store its pid because it always has access to it.
So what are writing is a script that essentially manages daemon processes , is that really what you want?
PS: do yourself a favour and get to know the argparse library.
import argparse
parser = argparse.ArgumentParser(description='Some Description')
parser.add_argument('command', help='Either stop or start', choices=['start', 'stop'])
args = parser.parse_args()
print(args.command)
It is well worth it

How do I get the Tor exit node IP address over the control port?

I want to monitor the status of running Tor instances.
I am already able to get information via a TCP connection to the control ports.
E.g. "GETINFO stream-status" returns data, but I am not able to determine the IP address of the currently chosen exit node.
It would be possible to simply request something like whatismyip.org, but that is too slow and does not scale well.
So what is the best way to get the exit node IP address of a Tor connection?
This is a great question! Here's a short script for doing it using stem...
from stem import CircStatus
from stem.control import Controller
with Controller.from_port(port = 9051) as controller:
controller.authenticate()
for circ in controller.get_circuits():
if circ.status != CircStatus.BUILT:
continue
exit_fp, exit_nickname = circ.path[-1]
exit_desc = controller.get_network_status(exit_fp, None)
exit_address = exit_desc.address if exit_desc else 'unknown'
print "Exit relay"
print " fingerprint: %s" % exit_fp
print " nickname: %s" % exit_nickname
print " address: %s" % exit_address
print
Thanks for the question. I've added this to our FAQ.
You can use tor control api. But I don't see the point.
You know the exit node id~name, you know the ip address that it is listening on. You don't know what network interface and what ip address it will use to process your query.
I've just checked that about 5% of tor exit nodes uses unpublished ipv4 addresses.
The world is moving to ipv6. These ip addresses are cheap. Each exit node can have a bag of ipv6 unpiblished addresses.
The exit circuit might be any one of the circuits returned by controller.get_circuits(), the following is how you get the exit circuit and the ip address:
source and tutorial link
## https://stem.torproject.org/tutorials/examples/exit_used.html
import functools
from stem import StreamStatus
from stem.control import EventType, Controller
def main():
print("Tracking requests for tor exits. Press 'enter' to end.")
print("")
with Controller.from_port() as controller:
controller.authenticate()
stream_listener = functools.partial(stream_event, controller)
controller.add_event_listener(stream_listener, EventType.STREAM)
input() # wait for user to press enter
def stream_event(controller, event):
if event.status == StreamStatus.SUCCEEDED and event.circ_id:
circ = controller.get_circuit(event.circ_id)
exit_fingerprint = circ.path[-1][0]
exit_relay = controller.get_network_status(exit_fingerprint)
print("Exit relay for our connection to %s" % (event.target))
print(" address: %s:%i" % (exit_relay.address, exit_relay.or_port))
print(" fingerprint: %s" % exit_relay.fingerprint)
print(" nickname: %s" % exit_relay.nickname)
print(" locale: %s" % controller.get_info("ip-to-country/%s" % exit_relay.address, 'unknown'))
print("")
if __name__ == '__main__':
main()
According to the Tor control protocol spec, the correct syntax is "GETINFO address", which should render the best guess at our external IP address. If we have no guess, return a 551 error. (Added in 0.1.2.2-alpha)".

Resources