Syntax-Fehler - aber weshalb?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Kel
User
Beiträge: 7
Registriert: Freitag 22. November 2013, 16:22

Ich muss dieses Python-Script (http://www.cs.york.ac.uk/semeval-2013/t ... _tweets.py) ausführen, da ich die Daten brauche.
Anleitung -> http://www.cs.york.ac.uk/semeval-2013/t ... readme.txt

Also Python 3.3 installiert und nach kurzem googlen dann auch beautifulsoup4 runtergeladen und per CMD installiert unter Windows.

Im Grunde also nur ein einfaches
easy_install beautifulsoup4
python download_tweets.py input_file > output_file
Nachdem mir erstmal überall nur Fehler entgegenkamen hab ich gegoogelt und festgestellt, dass die Formatierung komplett für'n Arsch war, also erstmal alles per Hand korrigiert - siehe Code unten.
Nun wirft mir ein "python tweets.py" aber immernoch einen Syntax-Fehler bei Zeile 61 aus

Code: Alles auswählen

D:\>python tweets.py input_file > tweeter
  File "tweets.py", line 61
    print "\t".join(fields + [text]).encode('utf-8')
             ^
SyntaxError: invalid syntax
Woran liegt das und was kann ich da tun, ich brauch die Daten :?

Kompletter und bereinigter Code:

Code: Alles auswählen

#!/usr/bin/python

import sys
import urllib
import re
import json

from bs4 import BeautifulSoup

import socket
socket.setdefaulttimeout(10)

cache = {}

for line in open(sys.argv[1]):
	fields = line.rstrip('\n').split('\t')
	sid = fields[0]
	uid = fields[1]

	#url = 'http://twitter.com/%s/status/%s' % (uid, sid)
	#print url
    

	tweet = None
	text = "Not Available"
	if cache.has_key(sid):
		text = cache[sid]
	else:
					try:
						f = urllib.urlopen("http://twitter.com/%s/status/%s" % (uid, sid))
                        #Thanks to Arturo!
						html = f.read().replace("</html>", "") + "</html>"
						soup = BeautifulSoup(html)

						jstt   = soup.find_all("p", "js-tweet-text")
						tweets = list(set([x.get_text() for x in jstt]))
						#print len(tweets)
			#print tweets
						if(len(tweets)) > 1:
							continue

						text = tweets[0]
						cache[sid] = tweets[0]

						for j in soup.find_all("input", "json-data", id="init-data"):
								js = json.loads(j['value'])
								if(js.has_key("embedData")):
										tweet = js["embedData"]["status"]
										text  = js["embedData"]["status"]["text"]
										cache[sid] = text
										break
					except Exception:
						continue

					if(tweet != None and tweet["id_str"] != sid):
						text = "Not Available"
						cache[sid] = "Not Available"
						text = text.replace('\n', ' ',)
						text = re.sub(r'\s+', ' ', text)
        #print json.dumps(tweet, indent=2)
						print "\t".join(fields + [text]).encode('utf-8')
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Kel,

das Programm ist auch für Python 2.x geschrieben, da muß es also nicht wundern, dass Python 3 einen Syntaxfehler meldet.
Benutzeravatar
Zennoe
User
Beiträge: 16
Registriert: Montag 12. August 2013, 21:46

Hier noch ein Tipp:
Unter http://docs.python.org/3.3/library/2to3.html findest du erklärt, wie du dein Skrip in eine Version von Python 3 umwandelst. Du musst also in der Python-Konsole folgenden Befehl ausführen:

Code: Alles auswählen

2to3 -w dateiname.py
Die Datei wird entsprechend umgeändert. Zudem wird ein Backup mit der alten Version erstellt.

Alternativ kannst du dir auch einfach den alten Python 2.7-Interpreter installieren. Unter Linux muss man dann python2 verwenden.

Hoffe es hat geholfen :wink:

Code: Alles auswählen

print("Zennoe sprach!")
Ja, das hat er!
Kel
User
Beiträge: 7
Registriert: Freitag 22. November 2013, 16:22

Gesagt, getan - neuer Syntaxfehler :lol:

Code: Alles auswählen

D:\>python tweets.py > test
Traceback (most recent call last):
  File "tweets.py", line 15, in <module>
    for line in open(sys.argv[1]):
IndexError: list index out of range
Wenn ich sys.argv[1] auf sys.argv[0] setze, kommt der gleiche Fehler in Zeile 18, wenn ich da den Arraywert auch auf 0 läuft es ohne Fehler, macht aber auch irgendwie nichts, ich krieg keine Ausgabedatei? :K

2to3, umgewandelter Code:

Code: Alles auswählen

#!/usr/bin/python

import sys
import urllib.request, urllib.parse, urllib.error
import re
import json

from bs4 import BeautifulSoup

import socket
socket.setdefaulttimeout(10)

cache = {}

for line in open(sys.argv[1]):
	fields = line.rstrip('\n').split('\t')
	sid = fields[0]
	uid = fields[1]

	#url = 'http://twitter.com/%s/status/%s' % (uid, sid)
	#print url
    

	tweet = None
	text = "Not Available"
	if sid in cache:
		text = cache[sid]
	else:
					try:
						f = urllib.request.urlopen("http://twitter.com/%s/status/%s" % (uid, sid))
                        #Thanks to Arturo!
						html = f.read().replace("</html>", "") + "</html>"
						soup = BeautifulSoup(html)

						jstt   = soup.find_all("p", "js-tweet-text")
						tweets = list(set([x.get_text() for x in jstt]))
						#print len(tweets)
			#print tweets
						if(len(tweets)) > 1:
							continue

						text = tweets[0]
						cache[sid] = tweets[0]

						for j in soup.find_all("input", "json-data", id="init-data"):
								js = json.loads(j['value'])
								if("embedData" in js):
										tweet = js["embedData"]["status"]
										text  = js["embedData"]["status"]["text"]
										cache[sid] = text
										break
					except Exception:
						continue

					if(tweet != None and tweet["id_str"] != sid):
						text = "Not Available"
						cache[sid] = "Not Available"
						text = text.replace('\n', ' ',)
						text = re.sub(r'\s+', ' ', text)
        #print json.dumps(tweet, indent=2)
						print("\t".join(fields + [text]).encode('utf-8'))
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Kel hat geschrieben:Gesagt, getan - neuer Syntaxfehler :lol:

Code: Alles auswählen

D:\>python tweets.py > test
Traceback (most recent call last):
  File "tweets.py", line 15, in <module>
    for line in open(sys.argv[1]):
IndexError: list index out of range
Das ist eindeutig kein Syntaxfehler, sondern, wie es dort auch geschrieben steht, ein IndexError bei der Ausführung des Programms.

Du versuchst in sys.argv auf das Element mit dem Index 1 zuzugreifen und das ist offensichtlich nicht vorhanden. Woher sollte es auch kommen? Offensichtlich benötigt das Skript einen Kommandozeilenparameter.
Kel
User
Beiträge: 7
Registriert: Freitag 22. November 2013, 16:22

/edit ich hab die Twitter-ID-Datei vergessen, die als Input-Datei dient ..... :roll:
Jetzt rödelt das Programm, ob was bei rauskommt verrate ich, wenn es fertig gerattert hat.


Laut readme soll man das Skript mit

Code: Alles auswählen

python tweets.py input_file > output_file
aufrufen.

Gibt bei mir aber nur einen "File not Found"-Fehler.

Code: Alles auswählen

D:\>python tweets.py input_file > output_file
Traceback (most recent call last):
  File "tweets.py", line 15, in <module>
    for line in open(sys.argv[1]):
FileNotFoundError: [Errno 2] No such file or directory: 'input_file'
Ich brauch ja da 2 Parameter, wenn er auf den Indexwert 0 und 1 zugreift, aber ich hab keine Ahnung wie ich die konform angeben soll??
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Zuerst: Der Code ist fuer Python 2 geschrieben, also benutze Python2.7. `2to3` ist keine vollstaendige Automatisierung der Portierung, sondern eine _Hilfe_.

Und fuer die konkrete Fehlermeldung: Benutze eben auch eine Datei, die existiert. Wenn es keine Datei namens `input_file` im Verzeichnis "D:\\" gibt, wird Python dort nunmal auch keine finden. Der richtige Weg das Programm aufzurufen ist `python tweets.py PFAD_ZUR_DATEI` `> output_file` benutzt Unix Shell Ausgabeumleitung. Ich bin mir nicht sicher, ob es das fuer Windows auch gibt. Ohne wird die Ausgabe direkt in die Eingabeaufforderung ausgegeben.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

cofi hat geschrieben:Der richtige Weg das Programm aufzurufen ist `python tweets.py PFAD_ZUR_DATEI` `> output_file` benutzt Unix Shell Ausgabeumleitung. Ich bin mir nicht sicher, ob es das fuer Windows auch gibt.
Ja, gibt es. Gab es schon unter DOS.
Kel
User
Beiträge: 7
Registriert: Freitag 22. November 2013, 16:22

Ich hab jetzt

Code: Alles auswählen

D:\>python tweets.py testb.tsv > output_file
Oder

Code: Alles auswählen

D:\>python tweets.py testb.tsv
Aber da passiert .... nix :K.

Ich hab extra die Twitter-IDs auf 4 beschränkt zum testen, aber er führt das Skript in 3-4 Sekunden aus und das wars

testb.tsv
264183816548130816 15140428 "positive"
263405084770172928 591166521 "negative"
262163168678248449 35266263 "negative"
264249301910310912 18516728 "negative"
Keine Ausgabe in output_file oder in der Kommandozeile.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kel: das ist ja auch kein Wunder. Du fängst einfach irgendeine Exception stillschweigen ab. Du wirst also nie erfahren, warum welche Fehler es gibt, es wird einfach nichts ausgegeben.
Also lösch mal das try-except und behandle die Fehler, die man tatsächlich erwartet und aus gutem Grund ignorieren will.
Kel
User
Beiträge: 7
Registriert: Freitag 22. November 2013, 16:22

Sirius3 hat geschrieben:@Kel: das ist ja auch kein Wunder. Du fängst einfach irgendeine Exception stillschweigen ab.
Wie kommst du darauf, dass das mein Script ist?
Steht doch ganz klar, woher das Script ist :K.

Ich brauch nur die Daten, die das Script liefert, ansonsten hab ich mit dem Ding nichts zu tun, das Projekt für die Auswertung wird in Java gemacht, Univorgabe.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Es ist Dein Skript, weil Du etwas versuchst damit zu machen.
Ehrlich gesagt ist das Skript so schlecht geschrieben, dass ohne irgendwelche Kenntnisse in Python da nichts zu machen ist. Wann Du schon auf Java festgelegt bist, es gibt auch genügend HTML-Parser für Java.
Kel
User
Beiträge: 7
Registriert: Freitag 22. November 2013, 16:22

Sirius3 hat geschrieben:Es ist Dein Skript, weil Du etwas versuchst damit zu machen.
Okay, das stimmt.
Sirius3 hat geschrieben:Ehrlich gesagt ist das Skript so schlecht geschrieben, dass ohne irgendwelche Kenntnisse in Python da nichts zu machen ist.
:shock:
Ich hab 0 Python-Kenntnisse und auch keine Zeit mir welche anzueignen, die über Grundlagen hinausgehen, nen Parser zu basteln der mir Twitter-IDs einliest und Text ausgibt .... das dürfte 2-3 Monate bei mir dauern, in der Zeit muss das Java-Projekt schon fast fertig sein.
Kann doch nicht sein, dass ein vorgegebenes Script von Wissenschaftlern/Informatikern so miserabel ist???
Sirius3 hat geschrieben:Wenn Du schon auf Java festgelegt bist, es gibt auch genügend HTML-Parser für Java.
Einarbeiten in die Twitter-API ist nicht, dafür ist keine Zeit vorgesehen, das Script muss einfach laufen und mir die Daten ausgeben .... kann doch alles nicht sein :x.
BlackJack

@Kel: Natürlich kann es sein dass ein Skript von Wissenschaftlern so miserabel ist. Stell Dir vor da schreibt einer unter Zeitdruck ohne Zeit sich einzuarbeiten, etwas was nur mal eben schnell für die Arbeit funktionieren soll, was danach damit passiert ist ihm oder ihr vollkommen egal. Glaubst Du da kommt qualitativ guter Quelltext bei heraus? Du bist doch gerade genau in so einer Situation — Du musst Dich in ein Thema einarbeiten und ein kleines „Wegwerfskript” schreiben wofür Du eigentlich überhaupt keine Zeit hast. Wie weit oben bei Deinen Prioritäten ist es dass wie auch immer Deine Lösung nachher aussehen mag, da irgendwann jemand mit Deinem Code weiterarbeiten muss‽ ;-)

Dein Problem könnte vielleicht auch daher kommen, dass zumindest beim zuletzt gezeigten Quelltext die Einrückung mit ziemlicher Sicherheit falsch ist. Das ab Zeile 55 alles zu dem ``if``-Zweig gehört ist semantisch sicher falsch. Und das sieht auch alles viel zu stark eingerückt aus. Konvention ist vier Leerzeichen pro Ebene. Und wirklich *Leerzeichen* und keine Tabulatorzeichen.

Es könnte auch sein das Twitter mittlerweile die Verwendung der API nicht mehr ohne Authentifizierung erlaubt.
Kel
User
Beiträge: 7
Registriert: Freitag 22. November 2013, 16:22

Kleines Update - da mir das alles zu doof wurde und mein letzter Versuch das Aufsetzen einer Linux-VM gewesen wäre, hab ich einfach einen Freund zwangsrekrutiert, der CentOS auf seinem Laptop hat.
Kurz Python 2.7 runtergeladen, kompiliert, dieses Betautifulsoup4-Parserding dazu installiert, Skript runtergeladen, ausgeführt und voilà.
Alle Daten sind fertig :mrgreen:
- eventuell hätte es auch geklappt wenn ich einfach 2.7 unter Windows installiert hätte anstatt da mit dem 2to3.py-Skript das umzuwandeln, aber 2.7 setzt (im Gegensatz zu 3.3) keine automatischen Systempaths und hätte einen Rechnerneustart erfordert, was da aktuell aber nicht ging weil ich noch massig offener Sachen hatte, die ich nicht einfach schließen konnte.

Dauert nur elendig lange, weil die Twitter-API nur eine ID pro Aufruf erlaubt, also gut 26k einzelne Twitter-API-Aufrufe durch das Skript, aber war innerhalb eines Tages erledigt.
Meine Kommilitonen versuchen sich grade an Twitter4Java und einer automatischen Übersetzung des Skriptes in Java in Eclipse .... keine Ahnung was die geritten hat, die haben nichtmal versucht das Python-Skript mit Python auszuführen :K.
Wenn man nur einen Hammer hat, ist jedes Problem ein Nagel oder so :roll:.

Danke für die ganze Hilfe :D.
Antworten