PyMySQL can't connect to MySQL on localhost - python

I'm trying to connect to MySQL on localhost using PyMySQL:
import pymysql
conn = pymysql.connect(db='base', user='root', passwd='pwd', host='localhost')
but (both on Python 2.7 and Python 3.2) I get the error:
socket.error: [Errno 111] Connection refused
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' (111)")
I'm sure mysqld is running because I can connect using mysql command or phpMyAdmin. Moreover, I can connect using MySQLdb on Python 2 with nearly the same code:
import MySQLdb
conn = MySQLdb.connect(db='base', user='root', passwd='pwd', host='localhost')
It seems that the problem is on PyMySQL side rather than MySQL but I have no idea how to solve it.

Two guesses:
Run mysqladmin variables | grep socket to get where the socket is located, and try setting up a connection like so:
pymysql.connect(db='base', user='root', passwd='pwd', unix_socket="/tmp/mysql.sock")
Run mysqladmin variables | grep port and verify that the port is 3306. If not, you can set the port manually like so:
pymysql.connect(db='base', user='root', passwd='pwd', host='localhost', port=XXXX)

Seems like changing localhost to 127.0.0.1 fixes the error, at least in my configuration.
If it doesn't, I would look for errors in tcp sockets connection and, of course, post it as a bug in pymysql bugtrack.

I solved the issue by replacing localhost with 127.0.0.1 and changing the password to my MYSQL database password as shown below;
conn = pymysql.connect(
host = '127.0.0.1',
port = 3306,
user = 'root',
passwd = 'XXXXXXXXX',
db = 'mysql'
)

I met the same question and my solution is as follows:
Run ssh -fN -L 3307:mysql_host:3306 ssh_user#ssh_host in my terminal.
Then input your ssh password
conn = pymysql.connect(db='base', user='root', passwd='pwd', host='localhost')
This error occurs because database does not support link directly.

I asked why socket worked but not TCP and the answer was that bind-address in /etc/my.cnf was not set correctly. This could be your problem too since the socket methods works just fine but the TCP one does not.

Those who are strugging to connect localhost MySQL from dockerised flask-sqlalchemy or using pymysql, pls look into this thread, very usefull How to connect locally hosted MySQL database with the docker container

This worked for me:
import pymysql
db = pymysql.connect(host="localhost",port=8889,user="root",passwd="root")
cursor=db.cursor()
cursor.execute("SHOW DATABASES")
results=cursor.fetchall()
for result in results:
print (result)
if you want to find the port # go to mysql in terminal, and type:
SHOW VARIABLES WHERE Variable_name = 'hostname';
SHOW VARIABLES WHERE Variable_name = 'port';

I had this same problem on AWS - and turns out that my security group was blocking the connection. I temporarily opened up all connections and voila! It connected!
Do you have any type of FW or host-based FW that could be blocking the connection? I thought it was my code and all was fine. Also check the port you are connecting on.

If you are using Docker, you might need to use host.docker.internal instead of localhost.

I managed to solve my issue by using the port without any quotation like so:
port = 3306,

You need to add the port to the connection as well. Try this and it works fine.
pymysql(Module Name).connect(host="localhost", user="root", passwd="root", port=8889, db="db_name")

Related

Python - Connect MySQL through localhost not working but 127.0.0.1 is working?

I just setup a VPS with a Mysql Database on it. I'm able to log into the database in the SSH terminal with mysql -uroot -p however, the python file shown below is unable to form a connection, and errors with Access denied for root#localhost (using password: YES). I'm confused as to why this is happening. I'm 100% sure my password is correct. I'm using mysql.connector
Python file:
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="pwd",
database="db"
)
mycursor = mydb.cursor()
sql = "INSERT INTO test (tests) VALUES (%s)"
val = ("testing")
mycursor.execute(sql, val)
mydb.commit()
I'm a bit new to this DB and VPS stuff, so please bear with me if I don't understand on the first go.
Thanks!
In addition to #don's answer
I assume it has something to do with the dns not properly resolving localhost. I have experienced that before, but outside of just mapping localhost to 127.0.01 in the host's file,
This can also be fixed by changing a value in your /etc/mysql/my.cnf file.
It's likely your bind-address line is
bind-address = localhost
You can try changing it to
bind-address = 127.0.0.1
You can also set it to 0.0.0.0 but this will expose the connection to the outside world (inc. public IP), so this is highly not recommended but will solve the problem.

PyMySQL using localhost vs socket incoherant behaviour

I am using PyMySQL to connect to a database running on localhost. I can access the database just fine using the username/password combiunation in both the command line and adminer so the database does not appear to be the probem here.
My code is as follow. However, when using the host="127.0.0.1" options, I get an OperationalError and an Errno 111. Using the same code, but connecting via the socket Mariadb runs on is fine.
import pymysql.cursors
from pprint import pprint
# This causes an OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
# connection = pymysql.connect(
# host="127.0.0.1",
# port=3306,
# user="root",
# password="S3kr37",
# db="my_test",
# )
# This works.
connection = pymysql.connect(
user="root",
password="S3kr37",
db="my_test",
unix_socket="/var/lib/mysql/mysql.sock"
)
try:
with connection.cursor() as cursor:
sql = "select * from MySuperTable"
cursor.execute(sql)
results = cursor.fetchall()
pprint(results)
finally:
connection.close()
What am I doing wrong?
PS: Note that this question has the same problem but the solution offered is the socket. That is no good enough: I want to know why I cannot use the hostname as the documentation suggests.
Errorcode 2003 (CR_CONN_HOST_ERROR) is returned by the client library, in case the client wasn't able to establish a tcp connection to the server.
First you should check, if you can connect via telnet or mysql command line client to your server.
If not, check the server configuration file:
does the server run on port 3306?
is IPv4 disabled?
is skip-networking enabled?
is bind-address activated (with another IP?

Connect postgres and Python

I have a database available on a remote host. When I use putty and SSH, I am able to access it. The database itself has no password. Only, the SSH connection has a password. But, when I try to connect to it using Python, it asks for password. I'm new to postgres and paramiko.
Here's what I've tried:
import psycopg2
import paramiko
import time
t = paramiko.Transport(('xxx.com', 22))
t.connect(username="xxx", password='xxx')
c = paramiko.Channel(t)
conn = psycopg2.connect("dbname='xxx'")
curs = conn.cursor()
sql = "select * from xxx"
curs.execute(sql)
rows = curs.fetchall()
print(rows)
Other method that I tried was:
import os, psycopg2
os.system("ssh xxx#xxx.com -fNL 5432:localhost:5432 -p 22")
while True:
try:
conn = psycopg2.connect("dbname='xxx'")
curs = conn.cursor()
sql = "select * from xxx"
curs.execute(sql)
rows = curs.fetchall()
print(rows)
except:
print "I am unable to connect to the database"
This gives me a 'Could not request local forwarding' error.
Is there some other way to go about this?
I have a Windows 7 (x64) machine with Python 2.7. Please help me. Thanks.
You should connect to the remote server and make port forwarding of remote PostgreSQL to a local port.
Without paramiko, it's something like this:
# start port forwarding
$ ssh -L PGSQL_LOCAL_PORT:localhost:PGSQL_REMOTE_PORT user#xxx.com
# in python
psycopg.connect("dbname='xxx' host='localhost' port='PGSQL_LOCAL_PORT'")
Here is an example of doing this with paramiko
https://code.ros.org/trac/wg-ros-pkg/browser/pkg/trunk/paramiko/demos/forward.py?rev=30
Note: Port forwarding is blocking operation. So, you have to start port forwarding in separate thread/process.

ssh first with mysqldb in python

I'm trying to connect to a MySQL database on a remote server using MySQLdb in python. The problem is that first I need to SSH into the host, and then from there, I need to connect to the MySQL server. The problem I'm having, though, is that MySQLdb does not seem to have a way of establishing an SSH connection before connecting to the SQL server. I've checked the documentation but have not had any luck.
This is how I'm connecting:
conn = MySQLdb.connect(host = 'mysqlhost.domain.com:3306', user = 'user', passwd = 'password', db = 'dbname')
But what I really need is something like this:
conn = MySQLdb.connect(sshhost = 'sshhost.domain.com', sshuser = 'sshusername', sshpasswd = 'sshpasswd', host = 'mysqlhost.domain.com:3306', user = 'user', passwd = 'password', db = 'dbname')
Which is of course just made up. Can anyone make any recommendations?
I prefer keeping the tunnel within the python code, I did hate to create tunnels manually, or separately, thanks to sshtunnel library its very simple to use.
Here is some simple sample that will work for what you want.
import MySQLdb
from sshtunnel import SSHTunnelForwarder
with SSHTunnelForwarder(
('sshhost.domain.com', 22),
ssh_password="sshpasswd",
ssh_username="sshusername",
remote_bind_address=('mysqlhost.domain.com', 3306)) as server:
conn = MySQLdb.connect(host='127.0.0.1',
port=server.local_bind_port,
user='user',
passwd='password',
db='dbname')
Setup an ssh tunnel before you use MySQLdb.connect. The tunnel will make it appear as though you have the mysql running locally, set it up something like this
ssh user#host.com -L 9990:localhost:3306
here your local port 9990 will bind to 3306 on the remote host, -L stands for local, then 9990:localhost:3306 means LOCALPORT:
conn = MySQLdb.connect(host = 'mysqlhost.domain.com:9990', user = 'user', passwd = 'password', db = 'dbname')
notice the 9990.
Add your public ssh key of user to the host.com so that you dont have to type the password each time you want to setup the tunnel (use public key authentication).
If you need to do this within python there is python-to-ssh binding libraries you could call from within python to setup the tunnel for you.

python mysql connection problem

This code works fine:
import MySQLdb
db = MySQLdb.connect("localhost", "root", "","bullsorbit")
cursor = db.cursor()
cursor.execute("Select * from table where conditions'")
numrows = int(cursor.rowcount)
print 'Total number of Pages : %d ' % numrows
but if I give my IP address
db = MySQLdb.connect("192.168.*.*", "root", "","bullsorbit")
it will give this error
super(Connection, self).__init__(*args, **kwargs2)
_mysql_exceptions.OperationalError: (2003, "Can't connect to MySQL server on 'ip address' (111)")
Code 2003 is a standard MySQL client error:
Error: 2003 (CR_CONN_HOST_ERROR) Message: Can't connect to MySQL server on '%s' (%d)
I'd guess that your user is not allowed to connect to the MySQL server using an iP-address. What happens if you try a connection usign the MySQL commandline client?
$ mysql --host=192.168.1.1 -u root bullsorbit
with localhost you connect via loopback-interface.
with ip-addr you connect - as you connect from extern.
if your server allows only the local (loopback) connection
your ip-addr connection fails. (security!)
look at your mysql config, maybe only local-connections are allowed.
is the skip-networking switch off (in the mysql-conf) ?
#skip-networking
For the 2003 error, another possibility is that too many connections are being attempted in too short of time. I noticed this same behavior when I had 127.0.0.1 as my connect string. First I replaced it with localhost which got me further but still the same 2003 error. Then I saw that if I scaled back the number of calls the error disappeared completely.
Instead of:
db = MySQLdb.connect("192.168..", "root", "","bullsorbit")
try:
db = MySQLdb.connect(user="root", host="192.168..", db="bullsorbit")
Password will default to empty string and try the usual identity methods. Host will also default to localhost on default port.

Categories

Resources