How to connect to a mongoDB - python

I'm using mongoLabs to host my database and I want to connect to it from my app.
I'm also using the Motor module in pyMongo. I'm unsure where to instantiate the connection.
For instance I know that if the database was on same local machine as the app I would do this:
database = motor.MotorClient().open_sync().myDatabase
The mongoLab site says to include the following uri in the driver:
mongodb://<dbuser>:<dbpassword>#ds047057.mongolab.com:47057/myDatabase
But I cannot see how to create the connection to this database.
Thanks

It looks like MotorClient takes the same arguments as MongoClient:
https://github.com/ajdavis/mongo-python-driver/blob/motor/motor/init.py#L782
http://api.mongodb.org/python/current/api/pymongo/mongo_client.html
Given that, you should be able to use the URI like so:
database = motor.MotorClient("mongodb://<dbuser>:<dbpassword>#ds047057.mongolab.com:47057/myDatabase").open_sync().myDatabase

You should to specify connection settings for MotorClient following these manuals:
MotorClient takes the same constructor arguments as MongoClient, as well as, http://emptysquare.net/motor/pymongo/api/motor/motor_client.html#motor.MotorClient,
http://emptysquare.net/motor/pymongo/api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient
"The host parameter can be a full mongodb URI, in addition to a simple
hostname. It can also be a list of hostnames or URIs. Any port
specified in the host string(s) will override the port parameter. If
multiple mongodb URIs containing database or auth information are
passed, the last database, username, and password present will be
used. For username and passwords reserved characters like ‘:’, ‘/’,
‘+’ and ‘#’ must be escaped following RFC 2396."
db = database = motor.MotorClient('mongodb://<dbuser>:<dbpassword>#ds047057.mongolab.com:47057/myDatabase
').open_sync().myDatabase

Previous answers have got a bit outdated, so the correct way according to the docs and as worked for me:
import motor.motor_asyncio
import asyncio
from asyncio import coroutine
db = motor.motor_asyncio.AsyncIOMotorClient().database_name
https://motor.readthedocs.io/en/stable/tutorial-asyncio.html
https://github.com/mongodb/motor/blob/master/doc/tutorial-asyncio.rst

Related

Is there a way to not have to specify the user when connecting with psycogp2?

So just passing in the host and db name and not having to specify the user like:
host=blabla.co port=7000 dbname=ff_db
instead of:
host=blabla.co port=7000 dbname=ff_db user=some_user
The .pgpass file already has the user specified so I feel passing this in is redundant.
You can use the env var PGUSER. See the docs for all the options.

How to let Python try an alternate server if previous one throws an error

Within my configuration file, database uri looks like this: SQLALCHEMY_URI = f"postgresql://{USER}:{PASSWORD}#{SERVER}/{NAME}".
I want to use two different values for SERVER, depending on where to deploy the code - a default value, and another value in case previous one fails. Is it possible to do so?
If you are using, for example, sqlalchemy package than code should look like:
import sqlalchemy
try:
SQLALCHEMY_URI = f"postgresql://{USER}:{PASSWORD}#{SERVER}/{NAME}"
engine = sqlalchemy.create_engine(SQLALCHEMY_URI)
except sqlalchemy.errors.TimeoutError:
print('Connection error - using another server') # or some log, alert, whatever you like
SQLALCHEMY_URI = f"postgresql://{USER}:{PASSWORD}#{ANOTHER_SERVER}/{NAME}"
engine = sqlalchemy.create_engine(SQLALCHEMY_URI)

Python 2.5 informixdb connect parameters

I use Python 2.5 and informixdb. I want to connect with the database, but what are the parameters for the informixdb.connect() method?
I have
Hostname
Port
Databasename
User
Password
But what is the right order? Or how is the dsn String build?
The official documentation does not really help me.
The documentation says i can use
informixdb.connect(dsn)
but they do not explain how a DataSourceString should looks like. What arguments and in which order are needed.
Here is an link to the documentation.
And i know Python 2.5 is very old, but the database does not support Python 3.x i have tried it.
From the documentation at https://sourceforge.net/projects/informixdb/:
To do anything useful with InformixDB one must connect to a database. This is accomplished by calling informixdb.connect:
>>> import informixdb
>>> conn = informixdb.connect('db#daniel', user='me', password='something')
>>> conn
<_informixdb.Connection object at 0xb7d08e90>
informixdb.connect takes three arguments: A dsn which identifies the database and server to connect to, as recognized by ESQL's CONNECT statement (e.g. 'database#server', 'database', '#server') plus an optional user and a corresponding password.
If the dsn doesn't include a servername the value of the environment variable INFORMIXSERVER is used. When connecting without specifying the name of the database no database will be selected. This is useful for setting up a new database from within InformixDB.
Why not use the new "IfxPy" OpenInformix module?
https://github.com/OpenInformix/IfxPy
It has support for both 2.x and 3.x versions of Python.

Resolve Discovery path on App Engine Module

I want to build a client for my cloud endpoints in python like described in the Documentation.
I want to build the api from a Managed VM, so i get the path to the API by calling
modules.get_hostname(module="default")
This works fine for the devserver and i can create the complete path to the discovery endpoint, however on the live system this returns the url to a certain version like:
20150628t110011.default.guestbook.appspot.com
Thus the complete path to the API (default module) would be
https://20150628t110011.default.guestbook.appspot.com/_ah/api/discovery/v1/apis/guestbook/v1/rest?userIp=182.177.0.4"
But there is no discovery document, maybe due to the fact, that the certificate does not match a url that long and the https fails.
Is there a proper way to receive the base url to the default module? like so:
default.guestbook.appspot.com
because that would result in a working discovery endpoint:
https://default.guestbook.appspot.com/_ah/api/discovery/v1/apis/guestbook/v1/rest?userIp=182.177.0.4"
I would like to avoid doing string operations here, because on the local devserver this would not work as the module url resolves to something like localhost:1234.
You probably want to go through the GAE URl routing doc: https://cloud.google.com/appengine/docs/python/modules/routing#routing_via_url
Key points in there:
Google does not issue SSL certificates for double-wildcard domains
hosted at appspot.com, the certificate won't work for https://20150628t110011.default.guestbook.appspot.com
You can get the certificate to work using the -dot- delimiters; in particular the default version of the default
module can be accessed directly at guestbook.appspot.com
The problem gets even more complicated if your app has multiple modules and also if it's mapped to a custom domain.
While trying to address such complications I realized that modules.get_hostname() is nowadays no longer able to perform the original function that its name implies (I guess because of the multiple possible paths for accessing the same entity). Which probably explains why they won't attempt to fix the api to return a proper hostname: (see this Q&A)
But the info it can return (as applicable depending on the invocation arguments and the execution context) is IMHO extremely useful, allowing one to programatically obtain proper hostnames/URLs for all 3 possible app usage contextes: on the development server, on the .appspot.com domain and on custom domains mapping (including with hostname-based mapping):
<instance_id>.<module_version>.<module_name>.<app_name>.(appspot.com|<devserver_hostname>:<port#>)
This would be, for example, my approach for an app not interested in anything below the module name and using hostname-based custom domain dispatch routing - modules mapped to different hostnames):
def get_module_url(self, module_name='default'):
host_name = modules.get_hostname(module=module_name)
if os.environ.get('SERVER_SOFTWARE').startswith('Development'):
return 'http://' + host_name
app_name = app_identity.get_application_id()
split_name = self.request.host.split(':')[0].split('.')
if split_name[-2] == 'appspot':
new_host_name = app_name if module_name == 'default' else module_name + '-dot-' + app_name
else:
# custom hostname-based domain mapping, default module goes to `www`.mydomain.com
new_host_name = 'www' if module_name == 'default' else module_name
if app_name.endswith('-staging'):
# copy of the GAE app for staging purposes on mydomain.com
new_host_name += '-staging'
return '.'.join(['https://' + new_host_name] + split_name[1:])
As per this thread, unfortunately manual conversion is required to convert from the . hostname to -dot-.

Pass command line variables between Python files. Totally stuck

I have what seems like a very easy problem with an easy solution just beyond my reach.
My setup:
A) Driver file (runs the test script)
B) Connection file (using Requests)
C) Parameters file
The paramenters file has 6 variables with things like server IP, login, pass etc.
The Driver file has a praser which reads the properties file and fills in the blanks.
driver.py paramtersfile.csv
This works fine. However, I added a PORT variable to the parameters file which needs to be seen by B) Connection file. This connections file is never called explicitly, rather just imported into the driver file for its connection and cookie methods.
How do I carry over the parsed variables (from sys.argv) from paramtersfile.csv to the Connections file (or any other file which is used to run my script?
Thank you stackoverflow community
Edit:
I got it to work using the obvious way of passing on the arguments into the class (self.foo) of whatever module/file I needed.
My question from before was along the lines of this idea:
You do something like
loadproperties(propertiesfile)
then from any other python script you could just do
import propertyloader
which would load a list of immutable properties into the current space
Seems very convenient to just do
url = propertyloader.url
instead of
class Connect (host, port, pass, url):
self.url = url
loader = requests(secure, url)
blah blah blah...
Seems like a headache free way of sharing common parameters between different parts of the script.
Maybe there's still a way of doing this (extra credit question)
From the driver.py file, import the connections file as a module and pass the arguments you've parsed to the methods inside the module. Something like this:
#===inside driver.py===
import connections
params = parseFile(sys.argv) #get parameters from the csv file that is passed to the command line
connections.connect(params) #pass them to whatever method you need to call from connections
EDIT: It sounds like you're not writing your code in a modular way. You should stop thinking about your code in terms of files, but instead think of them in terms of modules: bits and pieces of interchangeable code that you can use in many different places. The main flaw with your design that I see (forgive me if I didn't understand correctly) is that you're hard-coding a value inside the connections file that you use to create connection objects. I'm guessing this is what your code looks like (or at least captures the spirit of your code adequately):
#connections.py
MY_SERVER = ??? #WHAT DO I SET THIS TO?
class Connection:
def __init__(self):
self.server = MY_SERVER
def connect():
connection = Connection() #create a new connection object
The above code is not designed well since you're defining a variable MY_SERVER that shouldn't be defined there in the first place! The connections class doesn't know or care what server it should use, it should work with any server. So where do you get the server variable? You pass it in via a constructor or a method. You could do something like this:
#connections.py
class Connection:
def __init__(self, server):
self.server = server
def connect(server):
connection = Connection(server) #create a new connection object with the server passed to the method
With this design, the Connection object becomes much more flexible. It is basically saying "I am a connection object that can handle any server. If you want to use me, just tell me what server you want to use!".
This way, in your drivers file you can first parse the server from your csv, and then simply call the method connections.connect by passing it the server you want!

Categories