引数なしで端末から「python
」を実行すると、Python Interactive Shell)が表示されます。
「cat | python
"ターミナルから対話モードを起動しません。どういうわけか、入力を取得せずに、パイプに接続されていることを検出しました。
C、C++、またはQtで同様の検出を行うにはどうすればよいですか?
isatty
を使用:
#include <stdio.h>
#include <io.h>
...
if (isatty(fileno(stdin)))
printf( "stdin is a terminal\n" );
else
printf( "stdin is a file or a pipe\n");
(Windowsでは、アンダースコアが接頭辞として付けられます:_isatty
、_fileno
)
多くのユースケースでは、 [〜#〜] posix [〜#〜] function isatty()
は、stdinが接続されているかどうかを検出するために必要なものすべてです。ターミナルへ。最小限の例:
_#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv)
{
if (isatty(fileno(stdin)))
puts("stdin is connected to a terminal");
else
puts("stdin is NOT connected to a terminal");
return 0;
}
_
次のセクションでは、さまざまなレベルの対話性をテストする必要がある場合に使用できるさまざまな方法を比較します。
プログラムが対話的に実行されているかどうかを検出する方法はいくつかあります。次の表に概要を示します。
cmd\method ctermid open isatty fstat ――――――――――――――――――――――――――――――――――― ――――――――――――――――――――――――――― ./ test/dev/tty OKはいS_ISCHR ./ test ≺test.cc/dev/tty OKいいえS_ISREG cat test.cc | ./test/dev/tty OKいいえS_ISFIFO echo ./test |現時点では/ dev/tty FAIL NO S_ISREG
結果は、次のプログラムを使用したUbuntu Linux 11.04システムからのものです。
_#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <iostream>
using namespace std;
int main() {
char tty[L_ctermid+1] = {0};
ctermid(tty);
cout << "ID: " << tty << '\n';
int fd = ::open(tty, O_RDONLY);
if (fd < 0) perror("Could not open terminal");
else {
cout << "Opened terminal\n";
struct termios term;
int r = tcgetattr(fd, &term);
if (r < 0) perror("Could not get attributes");
else cout << "Got attributes\n";
}
if (isatty(fileno(stdin))) cout << "Is a terminal\n";
else cout << "Is not a terminal\n";
struct stat stats;
int r = fstat(fileno(stdin), &stats);
if (r < 0) perror("fstat failed");
else {
if (S_ISCHR(stats.st_mode)) cout << "S_ISCHR\n";
else if (S_ISFIFO(stats.st_mode)) cout << "S_ISFIFO\n";
else if (S_ISREG(stats.st_mode)) cout << "S_ISREG\n";
else cout << "unknown stat mode\n";
}
return 0;
}
_
対話型セッションに特定の機能が必要な場合は、端末デバイスを開き、tcsetattr()
を介して必要な端末属性を(一時的に)設定できます。
インタープリターを対話的に実行するかどうかを決定するPythonコード はisatty()
を使用します。関数PyRun_AnyFileExFlags()
_/* Parse input from a file and execute it */
int
PyRun_AnyFileExFlags(FILE *fp, const char *filename, int closeit,
PyCompilerFlags *flags)
{
if (filename == NULL)
filename = "???";
if (Py_FdIsInteractive(fp, filename)) {
int err = PyRun_InteractiveLoopFlags(fp, filename, flags);
_
Py_FdIsInteractive()
を呼び出します
_/*
* The file descriptor fd is considered ``interactive'' if either
* a) isatty(fd) is TRUE, or
* b) the -i flag was given, and the filename associated with
* the descriptor is NULL or "<stdin>" or "???".
*/
int
Py_FdIsInteractive(FILE *fp, const char *filename)
{
if (isatty((int)fileno(fp)))
return 1;
_
isatty()
を呼び出します。
双方向性にはさまざまな程度があります。 stdin
がパイプ/ファイルまたは実際の端末に接続されているかどうかを確認するには、isatty()
が自然な方法です。
Stat()またはfstat()を呼び出し、S_IFIFOがst_modeに設定されているかどうかを確認します。
「stdin」がfstatであるファイルのタイプをチェックしているのでしょう。
struct stat stats;
fstat(0, &stats);
if (S_ISCHR(stats.st_mode)) {
// Looks like a tty, so we're in interactive mode.
} else if (S_ISFIFO(stats.st_mode)) {
// Looks like a pipe, so we're in non-interactive mode.
}
もちろん、Pythonはオープンソースですので、彼らが何をしているのかを見て、確実に知ることができます:
Windowsでは、GetFileTypeを使用できます。
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD type = GetFileType(hIn);
switch (type) {
case FILE_TYPE_CHAR:
// it's from a character device, almost certainly the console
case FILE_TYPE_DISK:
// redirected from a file
case FILE_TYPE_PIPE:
// piped from another program, a la "echo hello | myprog"
case FILE_TYPE_UNKNOWN:
// this shouldn't be happening...
}
stat(0, &result)
を呼び出して、!S_ISREG( result.st_mode )
を確認できます。ただし、C/C++ではなく、Posixです。