当crontab启动python脚本时,了解python脚本需要从stdin中读取一些内容

当crontab启动python脚本时,了解python脚本需要从stdin中读取一些内容,python,linux,python-3.x,cron,stdin,Python,Linux,Python 3.x,Cron,Stdin,我有一个python脚本,由crontab运行,可以手动执行 此脚本将以下内容作为输入: -i参数中的值 或者通过管道从stdin来的任何东西 代码应该是这样的: if ???: #test to check if there is some data in stdin print("I have data from stdin!") else: print("I have no data from stdin!") 脚本按如下方式执行: $ ./myscript.py -i my

我有一个python脚本,由crontab运行,可以手动执行

此脚本将以下内容作为输入:

  • -i
    参数中的值
  • 或者通过
    管道从
    stdin
    来的任何东西
代码应该是这样的:

if ???: #test to check if there is some data in stdin
  print("I have data from stdin!")
else:
  print("I have no data from stdin!")
脚本按如下方式执行:

$ ./myscript.py -i myInput
> I have no data from stdin!

$ cat myInput | ./myscript.py
> I have data from stdin!
我已经尝试了几种方法,它们在通过控制台执行时工作正常,但在通过crontab执行时却没有达到预期效果:脚本总是认为有来自stdin的数据

第一次测试:

if not sys.stdin.isatty():
  print("I have data from stdin!")
else:
  print("I have no data from stdin!")
我认为这一条不起作用,因为crontab模式中没有tty,所以第一条语句总是正确的

第二次测试:

import stat
mode = os.fstat(sys.stdin.fileno()).st_mode
if stat.S_ISFIFO(mode):
  print("I have data from stdin!")
else:
  print("I have no data from stdin!")
第三项测试:

import select
r, w, x = select.select([sys.stdin], [], [], 0)
if r:
  print("I have data from stdin!")
else:
  print("I have no data from stdin!")

有没有一种正确的方法可以使它同时适用于控制台和crontab模式?

由于Nullman已经在评论中写道,最好检查您的命令行选项,以决定是否要尝试使用stdin

简短摘要:通过检查
stdin
,您无法安全地猜测是否应从
stdin
读取数据。您应该只依靠检查命令行来了解所需内容

例如,
cat
仅当未将输入文件指定为命令行参数或指定了特殊文件名
-
时才会使用
stdin


示例中的所有测试仅在某些情况下有效,在其他情况下无效

检查
stdin
是否为TTY没有帮助。它只会告诉您它是否连接到终端。如果用户键入某个内容,或者是连接到其他内容的伪终端,则脚本可以从终端获取输入。如果脚本未连接到终端,而是连接到其他对象(管道、文件、套接字等),则还可以从stdin获取输入

检查stdin是否为FIFO也是错误的,因为您可以从管道/FIFO或其他东西(文件、套接字、终端等)读取数据

使用
select
不会告诉您是否有任何数据,但只有在
读取时才会告诉您。它也不会阻塞EOF。要区分这些情况,您必须从
stdin
检查
读取的结果。如果没有延迟/超时,它还可能会告诉您,如果数据还不可用,
读取将被阻塞

有更多的方法可以使用脚本:

您也可以使用
/myscript.py
,而不是
cat myInput |/myscript.py
。在第一种情况下,
stdin
将是一个管道,在第二种情况下是一个文件

或者想象一下
/myscript.py
。这将在第一次读取时返回EOF条件
或者
/myscript.py,因为Nullman已经在一条评论中写到,最好检查命令行选项,以决定是否要尝试
stdin

简短摘要:通过检查
stdin
,您无法安全地猜测是否应从
stdin
读取数据。您应该只依靠检查命令行来了解所需内容

例如,
cat
仅当未将输入文件指定为命令行参数或指定了特殊文件名
-
时才会使用
stdin


示例中的所有测试仅在某些情况下有效,在其他情况下无效

检查
stdin
是否为TTY没有帮助。它只会告诉您它是否连接到终端。如果用户键入某个内容,或者是连接到其他内容的伪终端,则脚本可以从终端获取输入。如果脚本未连接到终端,而是连接到其他对象(管道、文件、套接字等),则还可以从stdin获取输入

检查stdin是否为FIFO也是错误的,因为您可以从管道/FIFO或其他东西(文件、套接字、终端等)读取数据

使用
select
不会告诉您是否有任何数据,但只有在
读取时才会告诉您。它也不会阻塞EOF。要区分这些情况,您必须从
stdin
检查
读取的结果。如果没有延迟/超时,它还可能会告诉您,如果数据还不可用,
读取将被阻塞

有更多的方法可以使用脚本:

您也可以使用
/myscript.py
,而不是
cat myInput |/myscript.py
。在第一种情况下,
stdin
将是一个管道,在第二种情况下是一个文件

或者想象一下
/myscript.py
。这将在第一次读取时返回EOF条件
或者
/myscript.py一个可能的解决方法是首先检查您是否获得了
-i
,这样您就不需要检查管道(我想到了:),但我希望在指定两者时考虑管道的值(不应该发生,但谁知道)。再加上现在我在寻找答案,我的好奇心一定会得到满足!当您试图从管道中获取数据时,它是冻结还是获得一些值(可能是空字符串)?如果它冻结,您可能会设置计时器上的读数,并在一秒钟后中止,如果您得到一个实际值,它是什么?它不会冻结,它将操作stdin中找到的任何值,可能是空的。一个可能的解决方法是先检查您是否得到
-i
,这样,您就不需要检查管道(我想到了:),但我希望在指定两者时考虑管道的值(不应该发生,但谁知道呢)。再加上现在我在寻找答案,我的好奇心一定会得到满足!当您试图从管道中获取数据时,它是冻结还是获得一些值(可能是空字符串)?如果它冻结了,你可能会设置一个计时器上的读数,然后