I am attempting to use Brickman to use Python coding on a LEGO EV3. When I try to run my code I get the following error
>>robot#ev3dev:~$ python3 CoffeePi_Test/Main.py
File "CoffeePi_Test/Main.py", line 14
tags=[‘coffeepi’]
^
SyntaxError: invalid character in identifier
Here is my code. I am not sure what is triggering this error.
#!/usr/bin/env python3
#Import the necessary methods from tweepy library
from tweepy.streaming import StreamListener
from tweepy import OAuthHandler
from tweepy import Stream
import json
import time
import vending
import ev3dev.ev3 as ev3
from ev3dev.auto import *
tags=[legovend]
words=[]
#Variables that contains the user credentials to access Twitter API
#Two versions, redudancy if the first fails...
access_token = # redacted
access_token_secret = # redacted
consumer_key = # redacted
consumer_secret = # redacted
access_token2 = # redacted
access_token_secret2 = # redacted
consumer_key2 = # redacted
consumer_secret2 = # redacted
#This is a basic listener that just prints received tweets to stdout.
class StdOutListener(StreamListener):
def on_data(self, data):
global mA,mB,home,cs, lastVend
try:
tweet = json.loads(data)
tw
except:
pass
if tags:
if all(tag in tweet['text'].lower() for tag in tags):
print (tweet['user']['screen_name'], ' - ', tweet['text'])
if int(tweet['timestamp_ms'])>lastVend:
ev3.Leds.set_color(ev3.Leds.LEFT, ev3.Leds.RED)
ev3.Leds.set_color(ev3.Leds.RIGHT, ev3.Leds.RED)
vending.onTweet(mA, mB, cs, home)
time.sleep(2)
lastVend = int(round(time.time() * 1000))+1000
ev3.Leds.set_color(ev3.Leds.LEFT, ev3.Leds.GREEN)
ev3.Leds.set_color(ev3.Leds.RIGHT, ev3.Leds.GREEN)
return True
def on_error(self, status):
print( status)
return False
if __name__ == '__main__':
#This handles Twitter authetification and the connection to Twitter Streaming API
print( 'here')
global mA,mB,home,cs, lastVend
mA = ev3.MediumMotor('outA')
mB = ev3.MediumMotor('outB')
home = mA.position - 40
cs=ColorSensor()
lastVend = int(round(time.time() * 1000))
l = StdOutListener()
auth = OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
stream = Stream(auth, l)
auth2 = OAuthHandler(consumer_key2, consumer_secret2)
auth2.set_access_token(access_token2, access_token_secret2)
stream2 = Stream(auth2, l)
try:
Sound.speak('Ready to go').wait()
print ('trying 1')
stream.filter(track=tags)
print('trying 2')
stream2.filter(track=tags)
Sound.speak('Could not connect').wait()
except Exception as e:
print( e)
Humor is usually not welcome on stackoverflow, but there are exceptions from this rule so let's this answer be such exception.
But let's go back to answering the actual question:
Can't determine cause of SyntaxError: invalid character in identifier
I am not sure what is triggering this error.
I have to admit that I write this fully correct answer with a chuckle :) :
The cause of the SyntaxError is an invalid character in identifier.
The invalid character in the identifier is the character:
[ ’ ]
U+2019 ’ e2 80 99 RIGHT SINGLE QUOTATION MARK
Here Python code with which you can find out for yourself details about the "character" which is causing the trouble:
#!/usr/bin/ python3
# -*- coding: <utf8> -*-
# tags=[’coffeepi’]
coffeepi = "’"
print(ord(coffeepi), hex(ord(coffeepi)), bin(ord(coffeepi)))
what prints:
8217, 0x2019 , 0b10000000011001
Check out this here
http://www.utf8-chartable.de/unicode-utf8-table.pl
where I have got the information about the character from, and this here
https://docs.python.org/3/reference/lexical_analysis.html#identifiers
for more detailed information about which characters are allowed in an indentifier, because not all are and apparently this one does not belong to the range of allowed characters.
By the way: this "character" is NOT a one byte character like it is for ASCII characters. How this character is encoded in UTF-8 is specified in the Unicode table (e2 80 99).
AND ... in the entire code you have provided in the question there is no trace of what you have specified to cause the error message.
How you can fix that?
Just replace these strange quotes with standard quotes " "
ADDENDUM: The strange quotes should be probably standard quotes around a string with a word put into the list. As the Python interpreter is running into this strange quotes it assumes they are part of a variable name (identifier) and not part of a string specification. That is the reason for the confusing error message as you don't see from the code at the first glance WHY the Python interpreter thinks it deals with an variable name (identifier) and not a quoted section of text which should be turned into a Python string.
Related
Python beginner here, I'm modifying a piece of existing code (TwitterSearch on Github) to search Twitter for specific tweets that contain certain keywords using standard search API. I keep getting a Syntax Error, but it points me to blank space at the end of a line.
The thing is, the code worked once yesterday (as in I got the output I wanted) and then I tried to use it again and it keeps giving me SyntaxError.
At one point the error was at the end of the code - I deleted the last few lines and the error would simply move to whatever the end of the code was (but it always pointed at blank space rather than anything I had typed). Now it's moved to the blank space after the closing brackets following 'created at' (see below)
I've been consistently indenting the same way throughout, so I don't think it's an indentation error. For reference, I'm using Jupyter Notebook.
This is the code I'm using:
try:
tso = TwitterSearchOrder()
tso.set_keywords(['xx'])
tso.set_language('en')
tso.set_geocode('37.0902000', '-095.7129000', '1mi')
ts = TwitterSearch(
consumer_key = 'xxxx',
consumer_secret = 'xxxx',
access_token = 'xxxx',
access_token_secret = 'xxxx'
)
for tweet in ts.search_tweets_iterable(tso):
print('#%s tweeted: %s' % (tweet['user']['screen_name'], tweet['text']), (tweet['created_at']))
except TwitterSearchException as e:
print('e')
Any help would be much appreciated.
Have you tried removing : from your print:(... statement?
try:
tso = TwitterSearchOrder()
tso.set_keywords(['xx'])
tso.set_language('en')
tso.set_geocode('37.0902000', '-095.7129000', '1mi')
ts = TwitterSearch(
consumer_key = 'xxxx',
consumer_secret = 'xxxx',
access_token = 'xxxx',
access_token_secret = 'xxxx'
)
for tweet in ts.search_tweets_iterable(tso):
print('#%s tweeted: %s' % (tweet['user']['screen_name'], tweet['text']), (tweet['created_at']))
except TwitterSearchException as e:
print(e)
So I'm working on a little mini project running off of a raspberry pi, of which the end goal is to have the pi running a python script to post a random image from a directory to twitter (a twitter bot). I have this code so far, and I'm getting an error. I'm assuming that the error is caused due to the fact that it is somehow not receiving the correct file type, but I'm not 100% sure. A little help would be fantastic!
import os
import random
from twython import Twython
#removed keys for privacy reasons
CONSUMER_KEY = ''
CONSUMER_SECRET = ''
ACCESS_KEY = ''
ACCESS_SECRET = ''
twitter = Twython(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_KEY, ACCESS_SECRET)
path = '/home/pi/DailyMeme/Memes/downloaded_images'
count = 0
file_list = []
for filename in os.listdir(path):
count = count+1
file_list.append(filename)
rnd = random.randint(0,count)
photo = open('/home/pi/DailyMeme/Memes/downloaded_images/'+file_list[rnd]+'.jpg','rb')
response = twitter.upload_media(media=photo)
twitter.update_status(status='check out this random meme', media_ids[response['media_id']])
EDIT: I'm new to python so it would be great if you could explain to me solutions
Error Message
File "random_meme.py", line 20
twitter.update_status(status='check out this random meme' , media_ids[response['media_id']])
SyntaxError: non-keyword arg after keyword arg
The issue is that once you have a keyword in the function call, in this case status all the following parameters in the function call must include a keyword.
Therefore you'll need to call this function either in different order of parameters or add a keyword to the second parameter
twitter.update_status(status='check out this random meme' , some_keyword=media_ids[response['media_id']])
(This is at least part of the issue regardless to what you actually want to achieve)
I'm working on a twitch irc bot and one of the components I wanted to have available was the ability for the bot to save quotes to a pastebin paste on close, and then retrieve the same quotes on start up.
I've started with the saving part, and have hit a road block where I can't seem to get a valid post, and I can't figure out a method.
#!/usr/bin/env python3
import urllib.parse
import urllib.request
# --------------------------------------------- Pastebin Requisites --------------------------------------------------
pastebin_key = 'my pastebin key' # developer api key, required. GET: http://pastebin.com/api
pastebin_password = 'password' # password for pastebin_username
pastebin_postexp = 'N' # N = never expire
pastebin_private = 0 # 0 = Public 1 = unlisted 2 = Private
pastebin_url = 'http://pastebin.com/api/api_post.php'
pastebin_username = 'username' # user corresponding with key
# --------------------------------------------- Value clean up --------------------------------------------------
pastebin_password = urllib.parse.quote(pastebin_password, safe='/')
pastebin_username = urllib.parse.quote(pastebin_username, safe='/')
# --------------------------------------------- Pastebin Functions --------------------------------------------------
def post(title, content): # used for posting a new paste
pastebin_vars = {'api_option': 'paste', 'api_user_key': pastebin_username, 'api_paste_private': pastebin_private,
'api_paste_name': title, 'api_paste_expire_date': pastebin_postexp, 'api_dev_key': pastebin_key,
'api_user_password': pastebin_password, 'api_paste_code': content}
try:
str_to_paste = ', '.join("{!s}={!r}".format(key, val) for (key, val) in pastebin_vars.items()) # dict to str :D
str_to_paste = str_to_paste.replace(":", "") # remove :
str_to_paste = str_to_paste.replace("'", "") # remove '
str_to_paste = str_to_paste.replace(")", "") # remove )
str_to_paste = str_to_paste.replace(", ", "&") # replace dividers with &
urllib.request.urlopen(pastebin_url, urllib.parse.urlencode(pastebin_vars)).read()
print('did that work?')
except:
print("post submit failed :(")
print(pastebin_url + "?" + str_to_paste) # print the output for test
post("test", "stuff")
I'm open to importing more libraries and stuff, not really sure what I'm doing wrong after working on this for two days straight :S
import urllib.parse
import urllib.request
PASTEBIN_KEY = 'xxx'
PASTEBIN_URL = 'https://pastebin.com/api/api_post.php'
PASTEBIN_LOGIN_URL = 'https://pastebin.com/api/api_login.php'
PASTEBIN_LOGIN = 'my_login_name'
PASTEBIN_PWD = 'yyy'
def pastebin_post(title, content):
login_params = dict(
api_dev_key=PASTEBIN_KEY,
api_user_name=PASTEBIN_LOGIN,
api_user_password=PASTEBIN_PWD
)
data = urllib.parse.urlencode(login_params).encode("utf-8")
req = urllib.request.Request(PASTEBIN_LOGIN_URL, data)
with urllib.request.urlopen(req) as response:
pastebin_vars = dict(
api_option='paste',
api_dev_key=PASTEBIN_KEY,
api_user_key=response.read(),
api_paste_name=title,
api_paste_code=content,
api_paste_private=2,
)
return urllib.request.urlopen(PASTEBIN_URL, urllib.parse.urlencode(pastebin_vars).encode('utf8')).read()
rv = pastebin_post("This is my title", "These are the contents I'm posting")
print(rv)
Combining two different answers above gave me this working solution.
First, your try/except block is throwing away the actual error. You should almost never use a "bare" except clause without capturing or re-raising the original exception. See this article for a full explanation.
Once you remove the try/except, and you will see the underlying error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "paste.py", line 42, in post
urllib.request.urlopen(pastebin_url, urllib.parse.urlencode(pastebin_vars)).read()
File "/usr/lib/python3.4/urllib/request.py", line 161, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.4/urllib/request.py", line 461, in open
req = meth(req)
File "/usr/lib/python3.4/urllib/request.py", line 1112, in do_request_
raise TypeError(msg)
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of type str.
This means you're trying to pass a unicode string into a function that's expecting bytes. When you do I/O (like reading/writing files on disk, or sending/receiving data over HTTP) you typically need to encode any unicode strings as bytes. See this presentation for a good explanation of unicode vs. bytes and when you need to encode and decode.
Next, this line:
urllib.request.urlopen(pastebin_url, urllib.parse.urlencode(pastebin_vars)).read()
Is throwing away the response, so you have no way of knowing the result of your API call. Assign this to a variable or return it from your function so you can then inspect the value. It will either be a URL to the paste, or an error message from the API.
Next, I think your code is sending a lot of unnecessary parameters to the API and your str_to_paste statements aren't necessary.
I was able to make a paste using the following, much simpler, code:
import urllib.parse
import urllib.request
PASTEBIN_KEY = 'my-api-key' # developer api key, required. GET: http://pastebin.com/api
PASTEBIN_URL = 'http://pastebin.com/api/api_post.php'
def post(title, content): # used for posting a new paste
pastebin_vars = dict(
api_option='paste',
api_dev_key=PASTEBIN_KEY,
api_paste_name=title,
api_paste_code=content,
)
return urllib.request.urlopen(PASTEBIN_URL, urllib.parse.urlencode(pastebin_vars).encode('utf8')).read()
Here it is in use:
>>> post("test", "hello\nworld.")
b'http://pastebin.com/v8jCkHDB'
I didn't know about pastebin until now. I read their api and tried it for the first time, and it worked perfectly fine.
Here's what I did:
I logged in to fetch the api_user_key.
Included that in the posting along with api_dev_key.
Checked the website, and the post was there.
Here's the code:
import urllib.parse
import urllib.request
def post(url, params):
data = urllib.parse.urlencode(login_params).encode("utf-8")
req = urllib.request.Request(login_url, data)
with urllib.request.urlopen(req) as response:
return response.read()
# Logging in to fetch api_user_key
login_url = "http://pastebin.com/api/api_login.php"
login_params = {"api_dev_key": "<the dev key they gave you",
"api_user_name": "<username goes here>",
"api_user_password": "<password goes here>"}
api_user_key = post(login_url, login_params)
# Posting some random text
post_url = "http://pastebin.com/api/api_post.php"
post_params = {"api_dev_key": "<the dev key they gave you",
"api_option": "paste",
"api_paste_code": "<head>Testing</head>",
"api_paste_private": "0",
"api_paste_name": "testing.html",
"api_paste_expire_date": "10M",
"api_paste_format": "html5",
"api_user_key": api_user_key}
response = post(post_url, post_params)
Only the first three parameters are needed for posting something, the rest are optional.
fwy the API doesn't seem to accept http requests as of writing this, so make sure to have the urls in the format of https://pas...
I am running this code to extract to get tweets. But running this code gives me a Syntaxerror : unexpected EOF while parsing. I am new to python so any help is appreciated! Thanks in advance.
from TwitterSearch import *
try:
tso = TwitterSearchOrder()
tso.setKeywords(['xyz', 'abc'])
tso.setLanguage('de') # we want to see German tweets only
tso.setCount(7) # please dear Mr Twitter, only give us 7 results per page
tso.setIncludeEntities(False) # and don't give us all those entity information
ts = TwitterSearch(
consumer_key = 'a',
consumer_secret = 'b',
access_token = 'c',
access_token_secret = 'd'
)
for tweet in ts.searchTweetsIterable(tso):
print('#%s tweeted: %s' % (tweet['user']['screen_name'], tweet['text']))
You need an except block at the end of your script:
except Exception, e:
print str(e)
I would suggest doing something aside from printing the exception and moving on, but this is the basic layout.
I'm trying to get authenticated by an API I'm attempting to access. I'm using urllib.parse.urlencode to encode the parameters which go in my URL. I'm using urllib.request.urlopen to fetch the content.
This should return 3 values from the server, such as:
SID=AAAAAAAAAAA
LSID=BBBBBBBBBBB
AUTH=CCCCCCCCCCC
The problem is it only returns the first value, and the trailing new line character.
import urllib.request
import urllib.parse
Emailparamx = 'Email'
Emailparam = Emailparamx.encode('utf-8')
email = 'myemail#stackoverflow.com'
email = email.encode('utf-8')
Passwdparam = 'Passwd'
Passwdparam = Passwdparam.encode('utf-8')
password = 'hidden'
password = password.encode('utf-8')
Accounttypeparam = 'accountType'
Accounttypeparam = Accounttypeparam.encode('utf-8')
accounttype = 'GOOGLE'
accounttype = accounttype.encode('utf-8')
Serviceparam = 'service'
Serviceparam = Serviceparam.encode('utf-8')
service = 'adwords'
service = service.encode('utf-8')
url = 'https://accounts.google.com/ClientLogin?'
urlen = url.encode('utf-8')
data = [(Emailparamx, email), (Passwdparam, password),
(Accounttypeparam, accounttype), (Serviceparam, service)]
auth = ''
dataurl = urllib.parse.urlencode(data)
accessurl = (url + "%s" % dataurl)
fh = urllib.request.urlopen(accessurl)
equals = '='
eqenc = equals.encode('utf-8')
try:
msg = fh.readline().split(eqenc)
print (msg)
And then msg prints
[b'SID', b'AAAAAAAAAAAAAAAAA\n']
I know that's some seriously ugly code, I'm about a week old in Python. Any help would be greatly appreciated.
The problem is that you're only calling readline once, so it only reads one line. If you want to read the lines one by one, you have to keep calling readline in a loop until done:
while True:
msg = fh.readline()
if not msg:
break
msg = msg.split(eqenc)
print(msg)
However, there's really no good reason to call readline here, because any file-like object (including a urlopen object) is already an iterable full of lines, so you can just do this:
for msg in fh:
print(msg)
Meanwhile, your original code has a try without an except or a finally, which will just raise a SyntaxError. Presumably you wanted something like this:
try:
for msg in fh:
print(msg)
except Exception as e:
print('Exception: {}'.format(e))
While we're at it, we can simplify your code a bit.
If you look at the examples:
Here is an example session that uses the GET method to retrieve a URL containing parameters:
That's exactly what you want to do here (except for the last line). All the extra stuff you're doing with encoding the strings is not only unnecessary, but incorrect. UTF-8 is the wrong encoding is the wrong encoding to use for URLs (you get away with it because all of your strings are pure ASCII); urlopen requires a string rather than an encoded byte string (although, at least in CPython 3.0-3.3, it happens to work if you give it byte strings that happen to be encoded properly); urlencode can take byte strings but may not do the right thing (you want to give it the original Unicode so it can quote things properly); etc.
Also, you probably want to decode the result (which is sent as ASCII—for more complicated examples, you'll have to either parse the fh.getheader('Content-Type'), or read the documentation for the API), and strip the newlines.
You also may want to build a structure you can use in your code instead of just printing it out. For example, if you store the results in login_info, and you need the SID in a later request, it's just login_info['SID'].
So, let's wrap things up in a function, then call that function:
import urllib.request
import urllib.parse
def client_login(email, passwd, account_type, service):
params = {'Email': email,
'Passwd': passwd,
'accountType': account_type,
'service': service}
qs = urllib.parse.urlencode(params)
url = 'https://accounts.google.com/ClientLogin?'
with urllib.request.urlopen(url + qs) as fh:
return dict(line.strip().decode('ascii').split('=', 1) for line in fh)
email = 'myemail#stackoverflow.com'
password = 'hidden'
accounttype = 'GOOGLE'
service = 'adwords'
try:
results = client_login(email, password, accounttype, service)
for key, value in results.items():
print('key "{}" is "{}".format(key, value))
except Exception as e:
print('Exception: {}'.format(e))