2010-07-22 6 views
59

Potrzebowałem mieć bezpośrednio wykonywalny skrypt pythona, więc uruchomiłem plik z #!/usr/bin/env python. Jednak potrzebuję również niebuforowanego wyjścia, więc próbowałem #!/usr/bin/env python -u, ale to nie powiedzie się z python -u: no such file or directory.Nie można przekazać argumentu do pythona za pomocą "#!/Usr/bin/env python"

I okazało się, że #/usr/bin/python -u działa, ale muszę to dostać python w PATH wspieranie środowisk wirtualnych env.

Jakie są moje opcje?

+1

Możesz rzucić okiem na to [pytanie SO] (http://stackoverflow.com/questions/881696/unbuffered-stdout-in-python-as-in-python--mrom-within-the-programu-), aby uzyskać trochę informacji o tym, jak wykonać niebuforowane wyjście. –

Odpowiedz

12

Podawanie argumentów do linii shebang nie jest standardem, a eksperymenty nie działają w połączeniu z env w systemie Linux. Rozwiązanie z bash polega na użyciu wbudowanego polecenia "set", aby ustawić wymagane opcje. Myślę, że możesz zrobić to samo, aby ustawić niebuforowane wyjście stdin za pomocą komendy python.

my2c

5

Jest to kludge i wymaga bash, ale to działa:

#!/bin/bash 

python -u <(cat <<"EOF" 
# Your script here 
print "Hello world" 
EOF 
) 
+1

Dzięki, to zadziałało dla mnie z innym problemem (używając powłoki mono csharp z argumentami) – IanNorton

12

Podczas korzystania shebang na Linuksie, cała reszta linii po nazwie interpretera jest interpretowany jako pojedyncza argument. python -u zostaje przekazany do env tak, jakbyś napisał: /usr/bin/env 'python -u'. Opcja /usr/bin/env wyszukuje plik binarny o nazwie python -u, którego nie ma.

36

W niektórych środowiskach env nie dzieli argumentów. Twój env szuka "python -u" na twojej ścieżce. Możemy używać sh do pracy. Zastąp swój shebang następującymi liniami kodu i wszystko będzie dobrze.

#!/bin/sh 
''''exec python -u -- "$0" ${1+"[email protected]"} # ''' 
# vi: syntax=python 

p.s. nie musimy się martwić o ścieżkę do sh, prawda?

+0

Tricky! Zastanawiam się, jak to jest przenośne. – d33tah

+1

Dla tych, którzy zastanawiają się, jak to działa: [Dlaczego ten opis działa?] (Http://stackoverflow.com/q/17458528) –

+12

['$ {1 +" $ @ "}' hack] (http: // www.perl.com/doc/FMTEYEWTK/sh_dollar_at) prawdopodobnie nie było potrzebne od co najmniej 20 lat :) – user4815162342

5

To może być trochę przestarzały, ale env (1) Instrukcja mówi, można użyć 'S' w tym przypadku

#!/usr/bin/env -S python -u 

Wydaje się, że działa całkiem dobrze na FreeBSD.

+7

nie działa w Ubuntu: 'invalid option' –

+0

również nie działa na Debianie Sid – wieczorek1990

+0

Nie działa w RHEL 7 eith er. – mikemaccana

8

Oto alternatywa skryptu do/usr/bin/env, która pozwala przekazywać argumenty na linii hash-bang, w oparciu o/bin/bash i z ograniczeniem, że spacje są zabronione w ścieżce wykonywalnej. Ja to nazywam "envns" (env bez spacji):

#!/bin/bash 

ARGS=($1) # separate $1 into multiple space-delimited arguments. 
shift # consume $1 

PROG=`which ${ARGS[0]}` 
unset ARGS[0] # discard executable name 

ARGS+=("[email protected]") # remainder of arguments preserved "as-is". 
exec $PROG "${ARGS[@]}" 

Zakładając ten skrypt znajdujący się w katalogu/usr/local/bin/envns, oto linia shebang:

#!/usr/local/bin/envns python -u 

Testowane na Ubuntu 13.10 i cygwin x64.

+2

To powinno być w pakiecie :) – wieczorek1990

4

Uwalnianie odpowiedzi Larry'ego Cai, env pozwala ustawić zmienną bezpośrednio w linii poleceń.Oznacza to, że -u może być zastąpiony przez równoważną PYTHONUNBUFFERED ustawienie przed python:

#!/usr/bin/env PYTHONUNBUFFERED="YESSSSS" python 

Works na RHEL 6.5. Jestem pewien, że funkcja env jest prawie uniwersalna.

+1

FYI, to nie działa w Debianie. Nie jestem pewien, dlaczego to nie działa (aby spojrzeć na wyjście 'ps' nie powinno być żadnej różnicy), ale nigdy nie wraca. Nie jest jasne, czy python w ogóle działa, kiedy robisz to w Debianie. Próbowałem tego w kilku miejscach - zdecydowanie nie działa zgodnie z oczekiwaniami w porównaniu do odpowiedniej linii poleceń. – MartyMacGyver

+0

@MartyMacGyver. Bardzo prawdopodobne, że zrobi to przy użyciu wersji 'env' lub nawet' python', której używasz. –

+0

Może to być wersja env, ale jak dotąd nie działa z żadnym nowoczesnym wariantem Debiana. Nie wydaje się, że Python faktycznie działa w tym scenariuszu na Debianie, co czyni go ograniczonym użytkowaniem poza niektórymi platformami i/lub konfiguracjami. – MartyMacGyver

-1

Niedawno napisał patch do wersji GNU Coreutils z env aby rozwiązać ten problem:

http://lists.gnu.org/archive/html/coreutils/2017-05/msg00018.html

Jeśli masz to, można zrobić:

#!/usr/bin/env :lang:--foo:bar 

env podzieli :lang:foo:--bar w polach lang, foo i --bar. Przeszuka ona PATH dla interpretera lang, a następnie wywoła go z argumentami --foo, bar oraz ścieżką do skryptu i argumentów tego skryptu.

Istnieje również funkcja przekazywania nazwy skryptu w środku opcji. Załóżmy, że chcesz uruchomić lang -f <thecriptname> other-arg, a następnie pozostałe argumenty. Mając to poprawione env, że odbywa się to tak:

#!/usr/bin/env :lang:-f:{}:other-arg 

maksymalna po lewej stronie pola, które jest odpowiednikiem {} otrzymuje z pierwszym argumentem, który następuje, które pod wezwaniem hash Wybuchu, to nazwa skryptu. Argument ten zostaje następnie usunięty.

Tutaj, other-arg może być coś przetworzonego przez lang lub coś przetworzonego przez skrypt.

Aby lepiej zrozumieć, zobacz liczne przypadki testowe echo w łatce.

Wybrałem znak :, ponieważ jest to istniejący separator używany w systemach PATH w systemach POSIX. Ponieważ env dokonuje wyszukiwania PATH, jest mało prawdopodobne, aby było używane dla programu, którego nazwa zawiera dwukropek. Znacznik {} pochodzi z narzędzia find, które używa go do oznaczenia wstawienia ścieżki do linii poleceń -exec.

+1

Dla każdego, kto to czyta i ma nadzieję, łata [została porzucona] (http://lists.gnu.org/archive/html/coreutils/2017-05/msg00025.html). –

Powiązane problemy