GNU/Linux >> Znalost Linux >  >> Linux

Python v raw režimu standardní tisk přidává mezery

Vypadá to, že provádíte pouze posun řádku, ale nevracíte vozík. Změňte svůj tisk na

print("ASD", end="\r\n")

Problém, se kterým se setkáváte, je rozdíl mezi režimy „raw“, „vařený“ a „cbreak“. A tyto režimy jsou režimy ovladače terminálu na úrovni jádra, nikoli režimy kódu vaší aplikace nebo standardní knihovny nebo čehokoli jiného v uživatelském prostoru. Toto je starý unixový způsob odkazování na ně. Posix je nahradil mnohem jemnější sadou atributů, i když atributy Posix jsou obvykle převráceny ve shodě s pomocnými funkcemi způsobem, který napodobuje staré režimy 'raw', 'cooked' a 'cbreak'.

V předpřipraveném režimu má samotný ovladač terminálu zabudovanou primitivní funkci pro úpravu řádků. Zvládá backspace, word erase (v podstatě backspace celé slovo najednou) a podobné věci. Nic sofistikovaného jako manipulace se šipkami nebo historií nebo něco podobného. Velmi primitivní. V tomto režimu váš program nikdy neuvidí nic z terminálu, dokud není odeslán znak konce řádku (eol), a pak váš program získá celý řádek a konec řádku je přeložen do unixového standardu 07 bez ohledu na to, co terminál skutečně dělá. V rámci toho také ovladač terminálu vrací zadané znaky zpět do terminálu, takže uživatel vidí, co píše.

V „vařeném“ režimu terminálový ovladač na úrovni jádra také provádí překlad výstupu. A součástí toho je otočení 15 do 27 v případě potřeby.

V „vařeném“ režimu terminálový ovladač také zpracovává speciální znaky, jako je Control-C (odesílá SIGINT skupině řídicích procesů (přeloženo CPythonem do výjimky KeyboardInterrupt)) a Control-Z (odesílá SIGTSTP (jako SIGSTOP, ale lze zachytit) do skupiny řídicích procesů).

V režimu 'cbreak' se již úpravy řádků neprovádějí. Ovladač terminálu poskytuje každý znak (nebo krátkou sekvenci znaků, jako je sekvence escape pro klávesu se šipkou) programu okamžitě. Tyto znaky se neodrážejí na obrazovce, takže pokud je váš program nevytiskne, uživatel je neuvidí. Ovladač terminálu však stále zpracovává speciální znaky, jako je Control-C a Control-Z, i když přestává zpracovávat znaky pro úpravu řádků, jako je backspace nebo znak pro mazání slov (typicky Control-W). Také se stále provádí určité výstupní zpracování, takže ovladač změní hodnotu 39 do 46 .

V režimu „raw“ se na vstupu ani výstupu neprovádí žádné zpracování. Žádná speciální manipulace se znaky, žádná ozvěna, žádná transformace 56 do 64 , žádná manipulace pro Control-Z, nic. Je na programu, který uvede terminál do surového režimu, aby to všechno udělal.

Nyní nastavujete atributy pro 71 takže si možná myslíte, že by to nemělo ovlivnit 86 . Ale ve skutečnosti oba vaše deskriptory souborů vedou k přesně stejné „instanci“ ovladače terminálu. A je to nastavení ovladače terminálu, které určuje, co se stane. Nezáleží tedy na tom, zda tato nastavení změníte pomocí 90 , 103 , nebo dokonce 116 , všechny mění stejnou základní instanci ovladače terminálu a ovlivňují všechny ostatní.

To samozřejmě neplatí pro deskriptory souborů, které byly přesměrovány shellem před spuštěním vašeho programu.

Jako vedlejší poznámku můžete použít 122 na příkazovém řádku, abyste viděli úplné načtení všech těchto příznaků (včetně toho, které řídicí znaky vedou k jakým signálům v režimech vaření a cbreak).


Google mě sem přivedl, když jsem hledal odpověď na stejnou otázku. Nápověda, kterou sdílel halex, že se nevrací kočár, mi pomohla najít pravdu. Své odpovědi jsem našel v příspěvku na Chrisově Wiki:https://utcc.utoronto.ca/~cks/space/blog/unix/CBreakAndRaw, který mě vedl k přečtení zdroje tty.py zde:https://hg. python.org/cpython/file/618ea5612e83/Lib/tty.pyCož mě přivedlo k závěru, že pokud je cílem číst jednotlivé znaky, místo:

tty.setraw()

Použijte:

tty.setcbreak()

Linux
  1. Je možné mít v terminálu vazby kláves Vim?

  2. Vytváření raw socketu v Pythonu bez práv roota

  3. Čtení v Pythonu s názvem PIPE

  1. Jak pěkně vytisknout soubor JSON v terminálu Linux

  2. Mac Terminal v[m] Editor Commands

  3. Spouštění pro příkazy terminálu smyčky v Jupyteru

  1. Pseudoterminál nebude přidělen, protože stdin není terminál

  2. Jak spustit python skript na terminálu (ubuntu)?

  3. python raw socket:Protokol není podporován