Apakah ada cara membaca satu karakter tunggal dari input pengguna? Misalnya, mereka menekan satu tombol di terminal dan dikembalikan (semacam suka getch()
). Saya tahu ada fungsi di Windows untuk itu, tapi saya ingin sesuatu yang lintas platform.
262
msvcrt.getch
denganmsvcrt.getwch
, seperti yang disarankan di sana.Jawaban:
Berikut tautan ke situs yang mengatakan bagaimana Anda bisa membaca satu karakter di Windows, Linux dan OSX: http://code.activestate.com/recipes/134892/
sumber
ImportError
pengecualian digunakan seperti semacam if-statement; mengapa tidak memanggil platform.system () untuk memeriksa OS?pada dasarnya akan membaca 1 byte dari STDIN.
Jika Anda harus menggunakan metode yang tidak menunggu,
\n
Anda dapat menggunakan kode ini seperti yang disarankan dalam jawaban sebelumnya:( diambil dari http://code.activestate.com/recipes/134892/ )
sumber
Resep ActiveState yang dikutip verbatim dalam dua jawaban direkayasa berlebihan. Ini bisa diringkas menjadi ini:
sumber
0
.Juga patut dicoba adalah pustaka readchar , yang sebagian didasarkan pada resep ActiveState yang disebutkan dalam jawaban lain.
Instalasi:
Pemakaian:
Diuji pada Windows dan Linux dengan Python 2.7.
Pada Windows, hanya kunci yang memetakan ke huruf atau kode kontrol ASCII yang didukung ( Backspace, Enter, Esc, Tab, Ctrl+ surat ). Pada GNU / Linux (tergantung pada terminal yang tepat, mungkin?) Anda juga mendapatkan Insert, Delete, Pg Up, Pg Dn, Home, Enddan kunci ... tapi kemudian, ada isu-isu yang memisahkan ini tombol khusus dariF nEsc .
Peringatan: Seperti dengan sebagian besar (semua?) Jawaban di sini, kunci sinyal seperti Ctrl+ C, Ctrl+ Ddan Ctrl+ Zditangkap dan dikembalikan ( masing - masing
'\x03'
,'\x04'
dan ,'\x1a'
masing - masing); program Anda bisa sulit dibatalkan.sumber
Metode alternatif:
Dari posting blog ini .
sumber
| os.O_NONBLOCK
. Kalau tidak, Anda bisa meletakkannya dalam satu lingkaran (ide yang bagus untuk tidur sebentar dalam lingkaran agar tidak berputar).while True
kemudianwhile 1
.Kode ini, berdasarkan di sini , akan menaikkan KeyboardInterrupt dan EOFError dengan benar jika Ctrl+ Catau Ctrl+ Dditekan.
Harus bekerja di Windows dan Linux. Versi OS X tersedia dari sumber aslinya.
sumber
Jawaban peringkat teratas (saat ini) (dengan kode ActiveState) terlalu rumit. Saya tidak melihat alasan untuk menggunakan kelas ketika fungsi belaka sudah cukup. Di bawah ini adalah dua implementasi yang mencapai hal yang sama tetapi dengan kode yang lebih mudah dibaca.
Kedua implementasi ini:
Versi 1: mudah dibaca dan sederhana
Versi 2: hindari impor berulang dan penanganan pengecualian:
[EDIT] Saya melewatkan satu keuntungan dari kode ActiveState. Jika Anda berencana membaca karakter beberapa kali, kode itu menghindari biaya (diabaikan) pengulangan impor Windows dan penanganan pengecualian ImportError pada sistem mirip Unix. Meskipun Anda mungkin harus lebih peduli tentang keterbacaan kode daripada optimasi yang dapat diabaikan, berikut adalah alternatif (mirip dengan jawaban Louis, tetapi getChar () mandiri) yang berfungsi sama dengan kode ActiveState dan lebih mudah dibaca:
Kode contoh yang menjalankan salah satu dari versi getChar () di atas:
sumber
Ini mungkin kasus penggunaan untuk manajer konteks. Mengesampingkan tunjangan untuk OS Windows, berikut saran saya:
sumber
self
dalam__enter__
dan memilikiread
metode yang kembalisys.stdin.read(1)
, maka Anda bisa membaca beberapa karakter dalam satu konteks.Coba gunakan ini: http://home.wlu.edu/~levys/software/kbhit.py Ini bukan pemblokiran (artinya Anda dapat memiliki loop sementara dan mendeteksi penekanan tombol tanpa menghentikannya) dan lintas-platform.
Contoh untuk menggunakan ini:
Atau Anda bisa menggunakan modul getch dari PyPi . Tapi ini akan memblokir loop sementara
sumber
Ini NON-BLOCKING, membaca kunci dan menyimpannya di keypress.key.
di program Anda
sumber
Jawaban di sini informatif, namun saya juga menginginkan cara untuk mendapatkan penekanan tombol secara tidak sinkron dan memadamkan penekanan tombol dalam acara terpisah, semuanya dengan cara yang aman, lintas platform. PyGame juga terlalu kembung untukku. Jadi saya membuat yang berikut ini (dengan Python 2.7 tapi saya curiga itu mudah dibawa-bawa), yang saya pikir saya akan bagikan di sini kalau-kalau itu berguna untuk orang lain. Saya menyimpan ini dalam file bernama keyPress.py.
Idenya adalah Anda bisa memanggil
keyPress.getKey()
, yang akan membaca kunci dari keyboard, lalu mengembalikannya.Jika Anda menginginkan sesuatu lebih dari itu, saya membuat
KeyCapture
objek. Anda dapat membuatnya melalui sesuatu sepertikeys = keyPress.KeyCapture()
.Lalu ada tiga hal yang dapat Anda lakukan:
addEvent(functionName)
menerima fungsi apa pun yang menggunakan satu parameter. Kemudian setiap kali tombol ditekan, fungsi ini akan dipanggil dengan string tombol itu sebagai inputnya. Ini dijalankan di utas terpisah, sehingga Anda dapat memblokir semua yang Anda inginkan di dalamnya dan itu tidak akan mengacaukan fungsi dari KeyCapturer atau menunda acara lainnya.get()
mengembalikan kunci dengan cara memblokir yang sama seperti sebelumnya. Sekarang diperlukan di sini karena kunci diambil melaluiKeyCapture
objek sekarang, sehinggakeyPress.getKey()
akan bertentangan dengan perilaku itu dan keduanya akan kehilangan beberapa kunci karena hanya satu kunci yang dapat diambil pada suatu waktu. Juga, katakan pengguna menekan 'a', lalu 'b', Anda meneleponget()
, pengguna menekan 'c'. Ituget()
panggilan akan segera kembali 'a', maka jika Anda menyebutnya lagi itu akan kembali 'b', kemudian 'c'. Jika Anda memanggilnya lagi itu akan memblokir sampai tombol lain ditekan. Ini memastikan bahwa Anda tidak melewatkan kunci apa pun, dengan cara memblokir jika diinginkan. Jadi dengan cara ini sedikit berbeda darikeyPress.getKey()
dari sebelumnyaJika Anda ingin perilaku
getKey()
kembali,get(lossy=True)
sepertiget()
, kecuali bahwa itu hanya mengembalikan tombol yang ditekan setelah panggilan keget()
. Jadi pada contoh di atas,get()
akan memblokir sampai pengguna menekan 'c', dan kemudian jika Anda memanggilnya lagi akan memblokir sampai tombol lain ditekan.getAsync()
sedikit berbeda. Ini dirancang untuk sesuatu yang melakukan banyak pemrosesan, kemudian sesekali kembali dan memeriksa tombol mana yang ditekan. Dengan demikiangetAsync()
mengembalikan daftar semua tombol yang ditekan sejak panggilan terakhir kegetAsync()
, dalam urutan dari tombol terlama ditekan ke tombol paling baru ditekan. Itu juga tidak memblokir, yang berarti bahwa jika tidak ada tombol yang ditekan sejak panggilan terakhir kegetAsync()
, sebuah kosong[]
akan dikembalikan.Untuk benar-benar mulai mengambil kunci, Anda perlu menelepon
keys.startCapture()
dengankeys
objek Anda yang dibuat di atas.startCapture
adalah non-blocking, dan hanya memulai satu utas yang hanya merekam penekanan tombol, dan utas lainnya untuk memproses penekanan tombol tersebut. Ada dua utas untuk memastikan bahwa utas yang merekam penekanan tombol tidak melewatkan kunci apa pun.Jika Anda ingin berhenti mengambil kunci, Anda dapat memanggil
keys.stopCapture()
dan itu akan berhenti mengambil kunci. Namun, karena menangkap kunci adalah operasi pemblokiran, kunci penangkap utas mungkin menangkap satu kunci lagi setelah memanggilstopCapture()
.Untuk mencegah hal ini, Anda dapat memasukkan parameter opsional ke dalam
startCapture(functionName, args)
dalam fungsi yang hanya melakukan sesuatu seperti memeriksa apakah kunci sama dengan 'c' dan kemudian keluar. Penting bahwa fungsi ini tidak banyak sebelum, misalnya, tidur di sini akan menyebabkan kita kehilangan kunci.Namun, jika
stopCapture()
dipanggil dalam fungsi ini, pengambilan kunci akan segera dihentikan, tanpa mencoba menangkap lagi, dan bahwa semuaget()
panggilan akan segera dikembalikan, dengan Tidak ada jika belum ada tombol yang ditekan.Juga, karena
get()
dangetAsync()
menyimpan semua tombol sebelumnya ditekan (sampai Anda mengambilnya), Anda dapat memanggilclearGetList()
danclearAsyncList()
melupakan tombol yang sebelumnya ditekan.Perhatikan bahwa
get()
,getAsync()
dan acara bersifat independen, jadi jika tombol ditekan: 1. Satu panggilan keget()
yang menunggu, dengan lossy aktif, akan mengembalikan kunci itu. Panggilan tunggu lainnya (jika ada) akan terus menunggu. 2. Kunci itu akan disimpan dalam antrian kunci get, sehinggaget()
dengan lossy off akan mengembalikan kunci tertua yang belum dikembalikanget()
. 3. Semua peristiwa akan dipecat dengan kunci itu sebagai input mereka 4. Kunci itu akan disimpan dalam daftargetAsync()
kunci, di mana kepar ini dikembalikan dan diatur ke daftar kosong pada panggilan berikutnya untukgetAsync()
Jika semua ini terlalu banyak, berikut adalah contoh kasus penggunaan:
Ini bekerja dengan baik untuk saya dari tes sederhana yang saya buat, tetapi saya akan dengan senang hati menerima umpan balik dari orang lain juga jika ada sesuatu yang saya lewatkan.
Saya memposting ini di sini juga.
sumber
Sebuah komentar di salah satu jawaban lain menyebutkan mode cbreak, yang penting untuk implementasi Unix karena Anda biasanya tidak ingin ^ C (
KeyboardError
) dikonsumsi oleh getchar (seperti ketika Anda mengatur terminal ke mode mentah, seperti yang dilakukan oleh sebagian besar jawaban lainnya).Detail penting lainnya adalah bahwa jika Anda ingin membaca satu karakter dan bukan satu byte , Anda harus membaca 4 byte dari aliran input, karena itulah jumlah maksimum byte yang terdiri dari satu karakter dalam UTF-8 (Python 3+ ). Membaca hanya satu byte akan menghasilkan hasil yang tidak terduga untuk karakter multi-byte seperti panah keypad.
Inilah implementasi saya yang berubah untuk Unix:
sumber
Coba ini dengan pygame:
sumber
pygame.error: video system not initialized
Resep ActiveState tampaknya mengandung sedikit bug untuk sistem "posix" yang mencegah
Ctrl-C
dari gangguan (saya menggunakan Mac). Jika saya memasukkan kode berikut dalam skrip saya:Saya tidak akan pernah bisa mengakhiri skrip dengan
Ctrl-C
, dan saya harus membunuh terminal saya untuk melarikan diri.Saya percaya baris berikut adalah penyebabnya, dan itu juga terlalu brutal:
Selain itu, paket
tty
tidak terlalu dibutuhkan,termios
sudah cukup untuk menanganinya.Di bawah ini adalah kode yang ditingkatkan yang berfungsi untuk saya (
Ctrl-C
akan menyela), dengangetche
fungsi tambahan yang menggemakan char saat Anda mengetik:Referensi:
sumber
The
curses
paket di python dapat digunakan untuk memasukkan "mentah" mode untuk input karakter dari terminal hanya dengan beberapa pernyataan. Penggunaan utama Curses adalah untuk mengambil alih layar untuk output, yang mungkin bukan yang Anda inginkan. Cuplikan kode ini menggunakanprint()
pernyataan sebagai gantinya, yang dapat digunakan, tetapi Anda harus menyadari bagaimana kutukan mengubah akhir baris yang melekat pada output.sumber
Jika saya melakukan sesuatu yang rumit saya akan menggunakan kutukan untuk membaca kunci. Tapi sering kali saya hanya ingin skrip Python 3 sederhana yang menggunakan pustaka standar dan dapat membaca tombol panah, jadi saya melakukan ini:
sumber
Solusi saya untuk python3, tidak tergantung pada paket pip apa pun.
sumber
Saya percaya bahwa ini adalah salah satu solusi paling elegan.
dan kemudian menggunakannya dalam kode:
sumber
Jawaban yang diterima tidak bekerja dengan baik untuk saya (saya akan memegang kunci, tidak ada yang akan terjadi, maka saya akan menekan tombol lain dan itu akan berhasil).
Setelah mempelajari tentang modul kutukan , sepertinya cara yang tepat untuk melakukannya. Dan sekarang tersedia untuk Windows melalui kursor Windows (tersedia melalui pip), sehingga Anda dapat memprogram dengan cara agnostik platform. Berikut ini contoh yang terinspirasi oleh tutorial yang bagus ini di YouTube:
Simpan dengan
.py
ekstensi, atau jalankancurses.wrapper(getkey)
dalam mode interaktif.sumber
Dijawab di sini: raw_input dengan python tanpa menekan enter
Gunakan kode ini-
Referensi: https://github.com/unfor19/mg-tools/blob/master/mgtools/get_key_pressed.py
sumber
Jika Anda ingin mendaftarkan hanya satu tombol, tekan sekalipun pengguna menekannya lebih dari satu kali atau terus menekan tombol lebih lama. Untuk menghindari beberapa input yang ditekan, gunakan loop sementara dan teruskan.
sumber
jika Anda hanya ingin memegang layar sehingga Anda dapat melihat hasilnya di terminal tulis saja
di akhir kode dan itu akan menahan layar
sumber
Build_input bawaan akan membantu.
sumber