Working with PRAW, in my main thread I've created a Reddit instance:
import praw
reddit = praw.Reddit(client_id='my client id',
client_secret='my client secret',
user_agent='my user agent')
Which works fine.
As the code grows, I've created various modules (.py
files) which the main .py
file where main
is imports them into.
There are times where these other modules need to access the above instance instead of creating a new one that would just waste resources or API rate limits.
In Python 3.6, what's the appropriate way to handle this? Are global variables just the answer here? It also does not seem very organized to pass this as a function argument dozens of times deep if there are a lot of functions being called.
You can put that code in its own module called reddit
reddit.py:
import praw
reddit = praw.Reddit(client_id='my client id',
client_secret='my client secret',
user_agent='my user agent')
And then use it like this.
some_other_module.py
import reddit
for submission in reddit.reddit.subreddit('learnpython').hot(limit=10):
print(submission.title)
Python will only run through the code in the module the first time it is imported, and then it keeps the module around internally so that on future imports the same module is referenced.
A little example you can do to see this is to create the following modules.
a.py
import b # j.x is now 4
import c # j.x is now 9
import j # j.x is still 9
print(j.x) # 9 is printed out
j.py
x = 1
b.py
import j
j.x += 3
c.py
import j
j.x += 5
The number 9 will be printed out because x was only set to 1 the very first time it was imported. Future references to the module where all using the same x.
In your case you could have main.py
and tdepend.py
import reddit.py
, and they would both be using the exact same reddit object.
FYI, you can use the following to see how close you are to reaching Reddit's API limits: praw.models.Auth(reddit).limits()
.
I had a similar problem in a project that I worked on, we ended up with 3 possible scenario:
Approach 1
In our case we, after some research, brainstorming etc., decided to solve it out through class
and I've to say it's working pretty well. The use of classes in python
has a LOT of advantages in these situations.
Let's say you have your tdepend.py
that defines a function caller()
that you need your reddit
instance in it :
def caller( a ) :
print( a.reddit )
then define a class and define reddit
as an attribute of the class, so it will be accessible from everywhere the class object is accessed. It's to say, you can also re-think of your main.py
script as a class object and all the variables as its attributes, as example:
import praw
from tdepend import caller
class MyClass() :
def __init__(self, name):
self.name = name
self.reddit = praw.Reddit(client_id='my client id',
client_secret='my client secret',
user_agent='my user agent')
### define bunch of other stuffs
a = MyClass( "a" )
caller( a )
### bunch of other functions on "a" object
this solution also allows you to define the class
in another script and simply import it, with reddit
and everything else you need in it already configured and just operate functions defined elsewhere on its objects (and believe me, it makes the organization and future needs to modify the code and remember where you defined everything a lot easier). It also allows you to pass a LOT of argument passing just one object and to reuse the same kind of attributes in different objects etc. I'm really happy with that.
Approach 2
If you don't wanna to go through class
you can also, for this particular situation, pass it as an argument (function( reddit )
) not only to avoid globals()
related-risks but also to make your code more readable when you will access it in future (e.g. when you will have to retrieve where the hell reddit
came from when reading one of these "dependency" file).
Approach 3
If for some reason you really don't want neither to pass it newer as argument nor pass a class object as argument (that allows you to pass in a single argument a bunch of other objects) you have to use globals()
but be well aware of the problems related with global variables and especially the future readability.
Hope it helps!
EDITED on your comments:
With classes you can do exactly what you asked: with this approach you make the API call when you create the a
object and that's all, no need to recall it, as you can see it remains the same (for the same object).
### main.py
caller(a)
<praw.reddit.Reddit object at 0x7f74d89a1470>
# the same
a.reddit
<praw.reddit.Reddit object at 0x7f74d89a1470>
### if you create another object of course it will be a different one
b = MyClass( "b" )
caller(b)
<praw.reddit.Reddit object at 0x7f74bf60bc88>
and if you have some function that need to acces the reddit element you created in MyClass()
in tdepend.py
within tdepend.py
only...just define them inside the class:
tdependclass.py
import praw
class MyClass() :
def __init__(self, name):
self.name = name
self.reddit = praw.Reddit(client_id='my client id',
client_secret='my client secret',
user_agent='my user agent')
### if you want to be called at the initiation of the object
self.redditStringized = str( self.reddit ) + " hello!"
### if you want to be able to decide when calling the function from main
def stringizeReddit( self, string ) :
return str( self.reddit ) + " " + string
### ... define a bunch of other stuffs and functions ...
main.py
:
from tdependclass import MyClass
from tdepend import caller
a = MyClass( "a" )
caller( a )
<praw.reddit.Reddit object at 0x7f00c787d668>
a.reddit
<praw.reddit.Reddit object at 0x7f00c787d668>
### called here
a.stringizeReddit( "hello!" )
'<praw.reddit.Reddit object at 0x7f00c787d668> hello!'
### defined at initiation of object
a.redditStringized
'<praw.reddit.Reddit object at 0x7f00c787d668> hello!'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With