Passing variable to another Python Script [duplicate] - python

This question already has answers here:
Python Unbound Method TypeError
(3 answers)
Closed 9 years ago.
I am having difficulty passing a variable from one function to another function in another python script. I have read the other answers but they have not really helped on this subject.
This is the first file I want to send the variable to( some code omitted for clarity )
# TestGUI.py
from Tkinter import *
import serial
import os
class Testgui:
def __init__(self, master):
def writetoBOT(self,instruct):
ser = serial.Serial(6)
ser.baudrate = 9600
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.timeout = 1 #non-block read
ser.writeTimeout = 2 #timeout for writ
if(ser.isOpen() == False):
ser.open()
print ser.portstr # check which port was really used
ser.write(instruct)
else :
ser.write(instruct)
This is the sceond file:
# TestGUI_2.py
from TestGUI import Testgui
class Tracker:
def __init__(self):
pass
def drive(self,cords, cords1):
while( cords >= 320):
l='l'
Testgui.writetoBOT(l) # This is the problem line
TypeError: unbound method writetoBOT() must be called with TestGUI instance as first argument (got str instance instead)

writetoBOT takes 2 arguments: self and instruct.
call it with a Testgui instance:
tgui=Testgui(your_master)
tgui.writetoBOT(l)
If you want to call it with Testgui class, you still need to pass an instance of Testgui:
tgui=Testgui(your_master)
Testgui.writetoBOT(tgui, l)

Alternatively, you can make common space for this two scripts, it acn by database - sqllite
For example,
# file1.py
import sqlite3
con = sqlite3.connect('messages.db')
cur = con.cursor()
#cur.execute('CREATE TABLE message (id INTEGER PRIMARY KEY, name TEXT, content TEXT, read INTEGER)')
#con.commit()
for x in range(100000):
if x in range(1, 500):
cur.execute('INSERT INTO message (id, name, content, read) VALUES(NULL, "Guido", "van Rossum", 0)')
con.commit()
# file2.py
import sqlite3
import time
con = sqlite3.connect('messages.db')
cur = con.cursor()
def listen():
messages = cur.execute('SELECT * FROM message WHERE read=0')
if not messages:
return False
for m in messages:
print 'get message ', m
cur.execute("UPDATE message SET read=1 WHERE id=?", m[0])
con.commit()
print 'update db'
return True
while True:
listen()
time.sleep(5)

You declared Testgui as a class. This is to be understood as a skeleton or wireframe (beware, this is a shortcut, not the reality). You need to first create a "real" object out from this skeleton in order to use it.
testgui=Testgui(amaster)
It is possible in classes to have methods (bound functions) that apply at class level. These are called static methods or class methods. They have to be decorated in python.
See http://en.wikipedia.org/wiki/Object_oriented_programming for more information.

Related

How to declare a integer outside of a function [duplicate]

This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 3 years ago.
I am trying to add data to my mysql database with a HTTP post request, but in the way it's set up now, if we post more than once, the data from the first post gets changed to 0 because I declare all the variables in the same definition. How can I fix this?
I have tried to declare a global variable in a second def, but it just loops that def instead of the one I have now.
#!/usr/bin/env python
import pymysql.cursors
from flask import Flask, request
from Crypto.Cipher import AES
connection = pymysql.connect('localhost','esp', 'password', 'points')
app = Flask(__name__)
#app.route('/post', methods = ["POST"])
def post():
hits1 = 0
hits2 = 0
punch1 = 0
punch2 = 0
kick1 = 0
kick2 = 0
takedown1 = 0
takedown2 = 0
print(request.data)
cipher = AES.new("abcdefghijklmnop")
decryptedData = cipher.decrypt(request.data)
data = decryptedData.decode("utf-8")
print(data)
print(data)
if(data[:1]=="e"):
if(data[1:2] == "1"):
hits1+=1
print(hits1)
if (data[:1]=="1"):
if(data[1:2]=="1"):
punch1+=1
elif(data[1:2]=="2"):
kick1+=1
elif(data[1:2]=="3"):
takedown1+=1
elif(data[:1]=="2"):
if(data[1:2]=="1"):
punch2+=1
elif(data[1:2]=="2"):
kick2+=1
elif(data[1:2]=="3"):
takedown2+=1
points1 = punch1 + kick1 * 2 + takedown1 * 3
points2 = punch2 + kick2 * 2 + takedown2 * 3
print(points1)
print(points2)
try:
with connection.cursor() as cursor:
cursor.execute("INSERT INTO points values({0}, {1}, {2}, {3}, {4}, {5})".format(1, hits1, kick1, punch1, takedown1, points1))
cursor.execute ("INSERT INTO points values({0}, {1}, {2}, {3}, {4}, {5})".format(2, hits2, kick2, punch2, takedown2, points2))
connection.commit()
print ("Data committed")
return 'ok'
except:
connection.close()
app.run(host='0.0.0.0', port= 8090)
The value of the previous post gets changed to 0, but i want to keep that value
It seems that you want to keep the variables you define at the top of your function (hits1, hits2...). The problem, as you stated, is that these variables are redefined every time your function is called.
The simplest way to do that (though a questionable design) is to use global variables. To define a global variable, you could do this:
hits1 = 0
hits2 = 0
# ...
#app.route('/post', methods = ["POST"])
def post():
global hits1, hits2
# ...
That way, the values will be kept between requests. A way that I (personnally) prefer, though it's still the same idea, is to keep your data in a "Storage" class:
class Storage:
hits1 = 0
hits2 = 0
# ...
#app.route('/post', methods = ["POST"])
def post():
# Instead of just using hits1, hits2, ...
# We now use Storage.hits1, ...
# Example:
# ...
Storage.points1 = Storage.punch1 + Storage.kick1 * 2 + Storage.takedown1 * 3
# ...
That works. But of course, this is forgotten every time you restart your Flask application. If you want actual persistence (which is what you're trying to achieve, as you're using a database), is something that would query the database (potentially with a cache in order to limit the number of queries) every time a user makes a request to your server:
class Database:
def __init__(self):
# Connect to your database
self._hits1 = None
#property
def hits1(self):
if self._hits1 is None:
# self._hits1 = (Load data from the database)
return self._hits1
# ...
database = Database()
#app.route('/post', methods = ["POST"])
def post():
# Loads from the database
hits1 = database.hits1
# ...
# In this case, you'd probably want to move your INSERT query to your database class
A few comments: if you want to keep your values between requests, it's probably that you want to UPDATE your database instead of INSERTing data (but that's just my interpretation of your code).
Also, using an_sql_request.format(data) is a very bad practice, as it can help potential SQL injections. Most database drivers offer a way of preparing queries. For example with mysql.connector:
cur = connection.cursor()
sql = "INSERT INTO MyTable (Col1, Col2) VALUES (%s, %s)"
cur.execute(sql, (value_for_col1, value_for_col2))

Calling method to another method in python

I have lots of database queries and I would like to use some methods to not repeat my code. I would like to call methods in other defined methods but it doesn't work
I'm getting such error:
class Main:
File "d.py", line 20, in Main
for word in getUserWords("SELECT users.mail, field_data_field_what_word_are_you_looking_.field_what_word_are_you_looking__value, users.uid FROM users INNER JOIN field_data_field_what_word_are_you_looking_ ON users.uid = field_data_field_what_word_are_you_looking_.entity_id"):
TypeError: getUserWords() takes exactly 2 arguments (1 given)
my code
import MySQLdb as mdb
Class Main:
def connect(self):
con = mdb.connect('***', '*****', '****', '***', charset="utf8", use_unicode=True)
return con
def cursor(self):
cursor = self.connect.cursor()
return cursor()
def getUserWords(self, sql):
self.sql = sql
self.cursor.execute(self.sql)
data = self.cursor.fetchall()
self.connect.commit()
self.connect.close()
return data
for word in getUserWords("SELECT users.mail, field_data_field_what_word_are_you_looking_.field_what_word_are_you_looking__value, users.uid FROM users INNER JOIN field_data_field_what_word_are_you_looking_ ON users.uid = field_data_field_what_word_are_you_looking_.entity_id"):
print word
Simpler example:
class Foo(object):
def __init__(self):
self.foo = "bar"
def function1(self,x):
self.function2(x)
def function2(self,y):
print y
bar = Foo()
bar.function1(3) # calls function1 which in turn calls function2 which prints out 3
bar.function2(4) # calls function 2 directly.
The main takeaway to answer your question:
If you have a class function, it has a first argument which is by convention self. If you call that class function on an instance (as in bar.function2), the self is implicit. If you call that class function from within the class (as when function1 calls function2), you need to do self.functionname, which again implicitly passes the self argument.
First point: instanciate your class and call getUserWords() on your instance:
import MySQLdb as mdb
class Main:
# snip
m = Main()
sql = your_sql_here
for word in m.getUserWords(sql):
print word
Second point: your implementation of Main is flawed.
Class Main:
def connect(self):
# this will open a new connection on each and every call
con = mdb.connect('***', '*****', '****', '***', charset="utf8", use_unicode=True)
return con
def cursor(self):
# this will
# 1. create a new connection on every call - which will
# never be closed since you don't keep a reference
# on it so you can close it
# 2. create a new cursor on every call
cursor = self.connect.cursor()
# and this one will raise a TypeError
# => "'Cursor' object is not callable"
return cursor()
# so I assume your real code is :
return cursor
def getUserWords(self, sql):
# assigning sql to self is totally useless here
self.sql = sql
# so (assuming self.cursor returns the cursor and not
# the call to the cursor), this will:
# - open a new connection
# - create a new cursor
# - execute the sql
# - and discards eveything (cursor and connection)
# without closing them
self.cursor.execute(self.sql)
# now we
# - open a second connection (without closing the first)
# - create a second cursor
# - call .fetchall() on it, which will raise a
# _mysql_exceptions.ProgrammingError
data = self.cursor.fetchall()
# we're not making it until this part because of
# the above error, but if we did, this would:
# - create yet a third connection and call .commit()
# on it - which in this case would mainly be a no-op
# since we have nothing to commit
self.connect.commit()
# and finally create a fourth connection and close it
# immediatly - note that this will be the only one that
# gets closed <g>
self.connect.close()
return data
A fixed version of your code could look something like this:
import MySQLdb as mdb
class Main(object):
def __init__(self, connection_data):
self._connection_data = connection_data.copy()
self._connection_data.update(charset="utf8", use_unicode=True)
self._db = None
#property
def db(self):
if self._db is None:
self._db = mdb.connect(**self._connection_data)
return self._db
def cursor(self):
return self.db.cursor()
def execute(self, sql):
cursor = self.cursor()
cursor.execute(self.sql)
for row in cursor:
yield row
self.db.commit()
cursor.close()
def __del__(self):
try:
self._db.close()
except:
# either it's not set or it's already closed
pass
m = Main(db="***", user="***", passwd="***")
for w in m.getUserWords(your_sql_here):
print w

error in sqlalchemy after replacing count query with exists query [duplicate]

This question already has an answer here:
query from sqlalchemy returns AttributeError: 'NoneType' object
(1 answer)
Closed 9 years ago.
class SourcetoPort(Base):
""""""
__tablename__ = 'source_to_port'
id = Column(Integer, primary_key=True)
port_no = Column(Integer)
src_address = Column(String,index=True)
#----------------------------------------------------------------------
def __init__(self, src_address,port_no):
""""""
self.src_address = src_address
self.port_no = port_no
def act_like_switch (self, packet, packet_in):
"""
Implement switch-like behavior.
"""
# Learn the port for the source MAC
#print "RECIEVED FROM PORT ",packet_in.in_port , "SOURCE ",packet.src
# create a Session
#Session = sessionmaker(bind=engine)
#session = Session()
self.mac_to_port[packet.src]=packet_in.in_port
#if self.mac_to_port.get(packet.dst)!=None:
print "count for dst",session.query(SourcetoPort).filter_by(src_address=str(packet.dst)).count(),str(packet.dst)
#if session.query(SourcetoPort).filter_by(src_address=str(packet.dst)).count():
if session.query(exists().where(SourcetoPort.src_address == str(packet.dst))).scalar() is not None:
#send this packet
print "got info from the database"
q_res = session.query(SourcetoPort).filter_by(src_address=str(packet.dst)).first()
self.send_packet(packet_in.buffer_id, packet_in.data,q_res.port_no, packet_in.in_port)
#create a flow modification message
msg = of.ofp_flow_mod()
#set the fields to match from the incoming packet
msg.match = of.ofp_match.from_packet(packet)
#send the rule to the switch so that it does not query the controller again.
msg.actions.append(of.ofp_action_output(port=q_res.port_no))
#push the rule
self.connection.send(msg)
else:
#flood this packet out as we don't know about this node.
print "flooding the first packet"
self.send_packet(packet_in.buffer_id, packet_in.data,
of.OFPP_FLOOD, packet_in.in_port)
#self.matrix[(packet.src,packet.dst)]+=1
entry = SourcetoPort(src_address=str(packet.src) , port_no=packet_in.in_port)
#add the record to the session object
session.add(entry)
#add the record to the session object
session.commit()
I have this peice of code.I replaced
#if session.query(SourcetoPort).filter_by(src_address=str(packet.dst)).count():
with
if session.query(exists().where(SourcetoPort.src_address == str(packet.dst))).scalar() is not None:
Now I am getting the following error.
File "/home/karthik/pox/tutorial.py", line 86, in act_like_switch
self.send_packet(packet_in.buffer_id, packet_in.data,q_res.port_no, packet_in.in_port)
AttributeError: 'NoneType' object has no attribute 'port_no'
^CINFO:core:Going down...
The above piece of code used to work with count query.Why is it now working with exists query.
As francis-avila explained in his brilliant answer to your other question there was issue in logic with exists()...scalar() is not None. It returns True or False - so it always return not None. Sorry it was my mistake while suggesting how to use exists in SQLAlchemy yesterday.
Other that that your code is correct and should work after changing logic of using exists() query results from:
if session.query(exists().where(SourcetoPort.src_address == str(packet.dst))).scalar() is not None:
to
if session.query(exists().where(SourcetoPort.src_address == str(packet.dst))).scalar():
Approach with using exists()...one() described here and handling exception would work too. Just keep in mind that handling exception is always more expensive operation (use more cpu cycles) in python then just doing condition check. If your application is not performance critical - using try/catch exception handling would be just fine.

Python method doesn't run in class

I am new to Python and can't seem to figure out why the .getRow method doesn't run. I created a DBMain class in dbMain.py and I am using pyTest.py to create the DBMain object to run getRow. When I run the debugger in Eclipse and DBMain's constructor does run but but when the getRow method is call nothing happens.
pyTest.py
import dbMain
def main():
db = dbMain.DbMain()
db.getRow()
if __name__ == '__main__':
main()
dbMain.py
##PydevCodeAnalysisIgnore
import pyodbc
class DbMain(object):
cncx = ''
def __init__(self):
cnxn = pyodbc.connect(driver='{SQL Server}',
server='server',
database='database',
uid='name',
pwd='pwd')
def getRow():
cursor = cnxn.cursor()
cursor.execute("select user_id, user_name from users")
row = cursor.fetchone()
return row
You do not return anything from getRow. Maybe you want to include something like
...
return row
Your getRow() method is not bound to the class. The signature for an instance method should look something like getRow(self) - the first parameter is the instance, which is received explicitly (but passed implicitly, when you call someinstance.method()).
To have something functional, you maybe should alter your dbMain to something like this:
##PydevCodeAnalysisIgnore
import pyodbc
class DbMain(object):
def __init__(self):
# make cnxn an attribute of the instance
self.cnxn = pyodbc.connect(driver='{SQL Server}', server='server',
database='database', uid='name', pwd='pwd')
# receive `self` explicitly
def getRow(self):
cursor = self.cnxn.cursor()
cursor.execute("select user_id, user_name from users")
row = cursor.fetchone()
# actually return something
return row
Further reading:
Python: Difference between class and instance attributes

Using var from from function A to function B

On this sample code i want to use the variables on the function db_properties at the function connect_and_query. To accomplish that I choose the return. So, using that strategy the code works perfectly. But, in this example the db.properties files only has 4 variables. That said, if the properties file had 20+ variables, should I continue using return? Or is there a most elegant/cleaner/correct way to do that?
import psycopg2
import sys
from ConfigParser import SafeConfigParser
class Main:
def db_properties(self):
cfgFile='c:\test\db.properties'
parser = SafeConfigParser()
parser.read(cfgFile)
dbHost = parser.get('database','db_host')
dbName = parser.get('database','db_name')
dbUser = parser.get('database','db_login')
dbPass = parser.get('database','db_pass')
return dbHost,dbName,dbUser,dbPass
def connect_and_query(self):
try:
con = None
dbHost=self.db_properties()[0]
dbName=self.db_properties()[1]
dbUser=self.db_properties()[2]
dbPass=self.db_properties()[3]
con = None
qry=("select star from galaxy")
con = psycopg2.connect(host=dbHost,database=dbName, user=dbUser,
password=dbPass)
cur = con.cursor()
cur.execute(qry)
data = cur.fetchall()
for result in data:
qryResult = result[0]
print "the test result is : " +qryResult
except psycopg2.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if con:
con.close()
operation=Main()
operation.connect_and_query()
Im using python 2.7
Regards
If there are a lot of variables, or if you want to easily change the variables being read, return a dictionary.
def db_properties(self, *variables):
cfgFile='c:\test\db.properties'
parser = SafeConfigParser()
parser.read(cfgFile)
return {
variable: parser.get('database', variable) for variable in variables
}
def connect_and_query(self):
try:
con = None
config = self.db_properties(
'db_host',
'db_name',
'db_login',
'db_pass',
)
#or you can use:
# variables = ['db_host','db_name','db_login','db_pass','db_whatever','db_whatever2',...]
# config = self.db_properties(*variables)
#now you can use any variable like: config['db_host']
# ---rest of the function here---
Edit: I refactored the code so you can specify the variables you want to load in the calling function itself.
You certainly don't want to call db_properties() 4 times; just call it once and store the result.
It's also almost certainly better to return a dict rather than a tuple, since as it is the caller needs to know what the method returns in order, rather than just having access to the values by their names. As the number of values getting passed around grows, this gets even harder to maintain.
e.g.:
class Main:
def db_properties(self):
cfgFile='c:\test\db.properties'
parser = SafeConfigParser()
parser.read(cfgFile)
configDict= dict()
configDict['dbHost'] = parser.get('database','db_host')
configDict['dbName'] = parser.get('database','db_name')
configDict['dbUser'] = parser.get('database','db_login')
configDict['dbPass'] = parser.get('database','db_pass')
return configDict
def connect_and_query(self):
try:
con = None
conf = self.db_properties()
con = None
qry=("select star from galaxy")
con = psycopg2.connect(host=conf['dbHost'],database=conf['dbName'],
user=conf['dbUser'],
password=conf['dbPass'])
NB: untested
You could change your db_properties to return a dict:
from functools import partial
# call as db_properties('db_host', 'db_name'...)
def db_properties(self, *args):
parser = SafeConfigParser()
parser.read('config file')
getter = partial(parser.get, 'database')
return dict(zip(args, map(getter, args)))
But otherwise it's probably best to keep the parser as an attribute of the instance, and provide a convenience method...
class whatever(object):
def init(self, *args, **kwargs):
# blah blah blah
cfgFile='c:\test\db.properties'
self._parser = SafeConfigParser()
self._parser.read(cfgFile)
#property
def db_config(self, key):
return self._parser.get('database', key)
Then use con = psycopg2.connect(host=self.db_config('db_host')...)
I'd suggest returning a namedtuple:
from collections import namedtuple
# in db_properties()
return namedtuple("dbconfig", "host name user password")(
parser.get('database','db_host'),
parser.get('database','db_name'),
parser.get('database','db_login'),
parser.get('database','db_pass'),
)
Now you have an object that you can access either by index or by attribute.
config = self.db_properties()
print config[0] # db_host
print config.host # same

Categories

Resources