Reputation: 7539
I try to make a non blocking api calls for OpenWeatherMap, but my problem is:
When i was doing tests on the file, and run it, the global api
was taking effect, but when importing the function, global
dont work anymore, and api
dident change: api = ""
?
Just after declaring the function i put global api
, and then when I use print 'The API link is: ' + api
I get the exact api
, but global
dident took effect!
Here is the code: https://github.com/abdelouahabb/tornadowm/blob/master/tornadowm.py#L62
What am I doing wrong?
When I import the file:
from tornadowm import *
forecast('daily', q='london', lang='fr')
The API link is: http://api.openweathermap.org/data/2.5/forecast/daily?lang=fr&q=london
api
Out[5]: ''
When executing the file instead of importing it:
runfile('C:/Python27/Lib/site-packages/tornadowm.py', wdir='C:/Python27/Lib/site-packages')
forecast('daily', q='london', lang='fr')
The API link is: http://api.openweathermap.org/data/2.5/forecast/daily?lang=fr&q=london
api
Out[8]: 'http://api.openweathermap.org/data/2.5/forecast/daily?lang=fr&q=london'
Edit: here is the code, if the Git got updated:
from tornado.httpclient import AsyncHTTPClient
import json
import xml.etree.ElementTree as ET
http_client = AsyncHTTPClient()
url = ''
response = ''
args = []
link = 'http://api.openweathermap.org/data/2.5/'
api = ''
result = {}
way = ''
def forecast(way, **kwargs):
global api
if way in ('weather', 'forecast', 'daily', 'find'):
if way == 'daily':
way = 'forecast/daily?'
else:
way += '?'
for i, j in kwargs.iteritems():
args.append('&{0}={1}'.format(i, j))
a = ''.join(set(args))
api = (link + way + a.replace(' ', '+')).replace('?&', '?')
print 'The API link is: ' + api
def handle_request(resp):
global response
if resp.error:
print "Error:", resp.error
else:
response = resp.body
http_client.fetch(api, handle_request)
else:
print "please put a way: 'weather', 'forecast', 'daily', 'find' "
def get_result():
global result
if response.startswith('{'):
print 'the result is JSON, stored in the variable result'
result = json.loads(response)
elif response.startswith('<'):
print 'the result is XML, parse the result variable to work on the nodes,'
print 'or, use response to see the raw result'
result = ET.fromstring(response)
else:
print '''Sorry, no valid response, or you used a parameter that is not compatible with the way!\n please check http://www.openweathermap.com/api for more informations''
Upvotes: 1
Views: 64
Reputation: 23068
It's the side effect of using global
.
When you do from tornadowm import *
your forecast()
function is, we could say metaphorically, "on its own" and is not "hard-linked" to your global space anymore.
Why? Because any effect you make on your global api
will "end" with your function, and the definition of api = ""
in your global space will take precedence.
Also, as a side note, it's not considered a good practice to use from something import *
. You should do from tornadowm import forecast
or even better, import tornadown
and then use tornadowm.forecast()
.
Even better, I just noticed your forecast()
function doesn't return anything. Which technically makes it not a function
anymore, but a procedure
(a procedure is like a function but it returns nothing, it just "does" stuff).
Instead of using a global
, you should define api
in this function and then return api
from it. Like this:
def forecast(blablabla):
api = "something"
blablabla
return api
And then
import tornadowm
api = tornadown.forecast(something)
And you're done.
Upvotes: 3
Reputation: 184121
Globals are global only to the module they're defined in. So, normally, you would expect tornadowm.api
to be changed when you call forecast
, but not api
in some other namespace.
The import *
is contributing to your understanding of the problem. This imports api
(among other names) into the importing namespace. This means that api
and tornadowm.api
initially point to the same object. But these two names are not linked in any way, and so calling forecast()
changes only tornadowm.api
and now the two names point to different objects.
To avoid this, don't use import *
. It is bad practice anyway and this is just one of the reasons. Instead, import tornadowm
and access the variable in the importing module as tornadowm.api
.
Upvotes: 2
Reputation: 20553
I'm afraid this is because global is coupled within module, by the time you from tornadowm import *
you have imported the api
name, but the global api won't take any effects within another module.
Upvotes: 1