Pfad übergabe "%~dp0" an Python unter Windows...

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ist starte mein Python Skript z.B. so: phlb.exe backup "%~dp0"

Windows konvertiert "%~dp0" zum aktuellen Pfad, also z.B.: "C:\foo\bar\"

In sys.argv kommt aber das an: 'C:\\foo\\bar"' :evil:

Gut, ein work-a-round mit .strip() tut's erstmal... Aber ist doch doof... oder gar ein Bug?!?


EDIT: Ach, ein work-a-round von außerhalb ist "%~dp0." in der batch zu nehmen. Das wird zu "C:\foo\bar\." und das in Python zu "C:\\foo\\bar\\." und per os.path.normpath() ist hinten dann alles weg: "C:\\foo\\bar"

Erinnere mich gerade daran, das robocopy (Ein tool von Microsoft selbst) das selbe Problem hat. Hab dazu bei http://ss64.com/nt/robocopy.html was gefunden:
If either the source or desination are a "quoted long foldername" do not include a trailing backslash as this will be treated as an escape character, i.e. "C:\some path\" will fail but "C:\some path\\" or "C:\some path\." or "C:\some path" will work.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Ist das denn überhaupt ein Python-Problem? Das sieht mir, insbesondere wenn das auch andere Programme betrifft, eher nach einem Problem der cmd.exe aus. Oder welche Shell da auch verwendet wird.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ja, wo der Ball genau liegt, weiß ich nicht...

Auf jeden Fall brauche ich einen funktionierenden work-a-round...

Noch ein anderes Problem:

Wenn noch ein Leerzeichen nach dem Pfad ist, wird der auch nicht weg gekürzt.
Bsp:
>>>"%~dp0"_<<< (Das "_" steht für ein Leerzeichen!)
wird zu:
>>>"C:\foo\bar\"_<<<
In sys.argv ist dann:
>>>'C:\\foo\\bar"_'<<<

Also work-a-round wäre dann besser: path = path.strip(" \"'")


Ist halt die Frage, was übergibt wirklich cmd.exe und was wird von Python "geändert" ?!?
Irgendwo passiert ja auch die Konvertierung von \ zu \\

Kann jemand mal folgendes mit Python 2 unter Windows testen:

Code: Alles auswählen

C:\>py -c "import sys;print(sys.argv)" C:\foo\bar\
['-c', 'C:\\foo\\bar\\']

C:\>py -c "import sys;print(sys.argv)" "C:\foo\bar\"
['-c', 'C:\\foo\\bar"']
Auch sehr interessant:

Code: Alles auswählen

C:\>py -c "import sys;print(sys.argv)" C:\foo\bar\ XXX
['-c', 'C:\\foo\\bar\\', 'XXX']

C:\>py -c "import sys;print(sys.argv)" "C:\foo\bar\" XXX
['-c', 'C:\\foo\\bar" XXX']
:shock:

Das Problem ist halt, das man gern "%~dp0" nimmt, weil damit auch Pfade mit Leerzeichen funktionieren.
Würde man nur %~dp0 ohne Anführungszeichen nehmen, werden Leerzeichen als neue Argumente angesehen.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@jens: Was meinst Du mit Konvertierung von \ zu \\? Das ist die normale `repr()`-*Darstellung* von Zeichenketten. Das verändert ja nichts an der Zeichenkette selbst, die auch weiterhin nur einfache Backslashes enthält. Da besteht also kein Problem.

Das zweite Beispiel das Du als *auch* sehr interessant benennst ist doch genau das ursprüngliche Problem.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ja, stimmt natürlich mit dem repr() Ausgabe...

Es wird ja auf jeden Fall was am Argument geändert. Das erste Anführungszeichen wird ja weggeschnitten... Die Frage ist, von vom: Von Python oder von Windows...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: Windows stellt sich ganz ausführlich selbst ein Bein.
Um innerhalb von " ein " schreiben zu können, muß es mit \ escaped werden. Ein "C:\python\" zählt das erste " als Beginn eines Arguments, das zweite " ist aber noch innerhalb des Arguments ein escaptes ", wird also so auch nach Python übergeben. Wird hinter dem \"_ noch ein Leerzeichen gesetzt zählt das Leerzeichen immer noch als innerhalb dieses Arguments, weil Windows automatisch ein fehlendes Anführungszeichen am Ende ersetzt. Das gesamte Argument lautet also "C:\python\" " wobei das erste und letzte (eventuell ausgelassene) Anführungszeichen nicht in argv landet, und das mittlere escapte Anführungszeichen aber schon (natürlich ohne Escapezeichen). Das Leerzeichen zählt dabei auch noch zum Argument (weil innerhalb der Anführungszeichen).

Bei %-Platzhaltern wird es jetzt ganz wild. Die Ersetzungsreichenfolge ist nämlich folgende. Bei einem "%~dp0" wird zuerst ersetzt (-> "C:\python\") dann werden die Argumente geparst, so dass der letzte Backslash zum Escapezeichen des Anführungszeichens wird. Als work-around müßte man also "%~dp0\" schreiben, denn das ergibt "C:\python\\" und somit wird der Doppel-Backslash als escapeter Backslash interpretiert und das zweite Anführungszeichen als Ende des Arguments.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Fazit: Windows macht Murks! :evil:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

jens hat geschrieben:Fazit: Windows macht Murks! :evil:
Die Windows-Entwickler tun sich nicht nur an dieser Stelle sehr schwer in der Shell-Entwicklung. Mit Unix-Shells habe ich deutlich bessere Erfahrungen gemacht. Das fangen selbst die vermeintlich smarten Cmdlets der PowerShell nicht wirklich auf.
Antworten