Этот запрос должен работать:
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE '%$username%'");
while($row = mysql_fetch_array($result))
{
echo $row['FirstName'];
}
Проблема заключается в одинарных кавычках, поэтому ваш запрос завершается с ошибкой и возвращает FALSE, и цикл WHILE не может выполняться. Использование% позволяет сопоставлять любые результаты, содержащие вашу строку (например, SomeText- $ username-SomeText).
Это просто ответ на ваш вопрос, вы должны реализовать материал, упомянутый в других сообщениях: обработка ошибок , используйте escape-строки (пользователи могут вводить что-либо в поле, и вы ДОЛЖНЫ убедиться, что это не произвольный код), используйте PDO вместо mysql_connect, который теперь лишен.
В Python 3.3 +:
from subprocess import STDOUT, check_output
output = check_output(cmd, stderr=STDOUT, timeout=seconds)
output
представляет собой байтовую строку, содержащую объединенные stdout команды, данные stderr.
Этот код повышает значение CalledProcessError
при ненулевом статусе выхода, как указано в тексте вопроса, в отличие от метода proc.communicate()
.
Я удалил shell=True
, потому что он часто используется без необходимости. Вы всегда можете добавить его обратно, если cmd
действительно требует его. Если вы добавите shell=True
, то есть, если дочерний процесс порождает своих потомков; check_output()
может вернуться намного позже, чем указывает таймаут, см. Ошибка тайм-аута подпроцесса .
Функция тайм-аута доступна на Python 2.x через subprocess32
backport модуля подпроцесса 3.2+.
Я изменил ответ sussudio. Теперь функция возвращает: (returncode
, stdout
, stderr
, timeout
) - stdout
и stderr
декодируется в строку utf-8
def kill_proc(proc, timeout):
timeout["value"] = True
proc.kill()
def run(cmd, timeout_sec):
proc = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
timeout = {"value": False}
timer = Timer(timeout_sec, kill_proc, [proc, timeout])
timer.start()
stdout, stderr = proc.communicate()
timer.cancel()
return proc.returncode, stdout.decode("utf-8"), stderr.decode("utf-8"), timeout["value"]
Вот решение Alex Martelli как модуль с надлежащим убийством процесса. Другие подходы не работают, потому что они не используют proc.communicate (). Поэтому, если у вас есть процесс, который производит много результатов, он заполнит свой выходной буфер, а затем заблокирует, пока вы не прочитаете что-нибудь из него.
from os import kill
from signal import alarm, signal, SIGALRM, SIGKILL
from subprocess import PIPE, Popen
def run(args, cwd = None, shell = False, kill_tree = True, timeout = -1, env = None):
'''
Run a command with a timeout after which it will be forcibly
killed.
'''
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
p = Popen(args, shell = shell, cwd = cwd, stdout = PIPE, stderr = PIPE, env = env)
if timeout != -1:
signal(SIGALRM, alarm_handler)
alarm(timeout)
try:
stdout, stderr = p.communicate()
if timeout != -1:
alarm(0)
except Alarm:
pids = [p.pid]
if kill_tree:
pids.extend(get_process_children(p.pid))
for pid in pids:
# process might have died before getting to this line
# so wrap to avoid OSError: no such process
try:
kill(pid, SIGKILL)
except OSError:
pass
return -9, '', ''
return p.returncode, stdout, stderr
def get_process_children(pid):
p = Popen('ps --no-headers -o pid --ppid %d' % pid, shell = True,
stdout = PIPE, stderr = PIPE)
stdout, stderr = p.communicate()
return [int(p) for p in stdout.split()]
if __name__ == '__main__':
print run('find /', shell = True, timeout = 3)
print run('find', shell = True)
ValueError: signal only works in main thread
– wim
3 August 2011 в 08:18
Если вы используете Unix,
import signal
...
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(5*60) # 5 minutes
try:
stdoutdata, stderrdata = proc.communicate()
signal.alarm(0) # reset the alarm
except Alarm:
print "Oops, taking too long!"
# whatever else
Ответ jcollado можно упростить, используя класс threading.Timer :
import shlex
from subprocess import Popen, PIPE
from threading import Timer
def run(cmd, timeout_sec):
proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)
timer = Timer(timeout_sec, proc.kill)
try:
timer.start()
stdout, stderr = proc.communicate()
finally:
timer.cancel()
# Examples: both take 1 second
run("sleep 1", 5) # process ends normally at 1 second
run("sleep 5", 1) # timeout happens at 1 second
lambda
: t = Timer(timeout, proc.kill)
– jfs
5 April 2014 в 22:43
Я мало знаю о деталях низкого уровня; но, учитывая, что в python 2.6 API предлагает возможность ждать потоков и завершать процессы, как запустить процесс в отдельном потоке?
import subprocess, threading
class Command(object):
def __init__(self, cmd):
self.cmd = cmd
self.process = None
def run(self, timeout):
def target():
print 'Thread started'
self.process = subprocess.Popen(self.cmd, shell=True)
self.process.communicate()
print 'Thread finished'
thread = threading.Thread(target=target)
thread.start()
thread.join(timeout)
if thread.is_alive():
print 'Terminating process'
self.process.terminate()
thread.join()
print self.process.returncode
command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)
Вывод этого фрагмента на моей машине:
Thread started
Process started
Process finished
Thread finished
0
Thread started
Process started
Terminating process
Thread finished
-15
, где можно видеть, что при первом выполнении процесс завершился правильно (код возврата 0), а во втором - завершение процесса (код возврата -15).
Я не тестировал в окнах; но, помимо обновления команды примера, я думаю, что она должна работать, поскольку я не нашел в документации ничего, что говорит о том, что thread.join или process.terminate не поддерживается.
Это решение убивает дерево процессов в случае оболочки = True, передает параметры процессу (или нет), имеет тайм-аут и получает вывод stdout, stderr и процесс обратного вызова (он использует psutil для kill_proc_tree) , Это было основано на нескольких решениях, размещенных в SO, включая jcollado's. Проводка в ответ на комментарии Ансона и юрида в ответ jcollado. Протестировано в Windows Srvr 2012 и Ubuntu 14.04. Обратите внимание, что для Ubuntu вам необходимо изменить вызов parent.children (...) parent.get_children (...).
def kill_proc_tree(pid, including_parent=True):
parent = psutil.Process(pid)
children = parent.children(recursive=True)
for child in children:
child.kill()
psutil.wait_procs(children, timeout=5)
if including_parent:
parent.kill()
parent.wait(5)
def run_with_timeout(cmd, current_dir, cmd_parms, timeout):
def target():
process = subprocess.Popen(cmd, cwd=current_dir, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
# wait for the process to terminate
if (cmd_parms == ""):
out, err = process.communicate()
else:
out, err = process.communicate(cmd_parms)
errcode = process.returncode
thread = Thread(target=target)
thread.start()
thread.join(timeout)
if thread.is_alive():
me = os.getpid()
kill_proc_tree(me, including_parent=False)
thread.join()
timeout
- packages.ubuntu.com/search?keywords=timeout - но ни один из них не работает в Windows, не так ли?
– Sridhar Ratnakumar
16 December 2011 в 20:00
К сожалению, я связан очень строгими политиками в отношении раскрытия исходного кода моим работодателем, поэтому я не могу предоставить фактический код. Но, по моему мнению, лучшим решением является создание подкласса, переопределяющего Popen.wait()
для опроса вместо ожидания на неопределенный срок, и Popen.__init__
для принятия параметра таймаута. Как только вы это сделаете, все остальные Popen
методы (которые вызывают wait
) будут работать, как ожидалось, включая communicate
.
Я добавил решение с потоком из jcollado
в мой модуль Python easyprocess .
Установка:
pip install easyprocess
Пример:
from easyprocess import Proc
# shell is not supported!
stdout=Proc('ping localhost').call(timeout=1.5).stdout
print stdout
Вы можете сделать это, используя select
import subprocess
from datetime import datetime
from select import select
def call_with_timeout(cmd, timeout):
started = datetime.now()
sp = subprocess.Popen(cmd, stdout=subprocess.PIPE)
while True:
p = select([sp.stdout], [], [], timeout)
if p[0]:
p[0][0].read()
ret = sp.poll()
if ret is not None:
return ret
if (datetime.now()-started).total_seconds() > timeout:
sp.kill()
return None
timeout
теперь поддерживается на call()
и communicate()
в модуле подпроцесса (как на Python3.3):
import subprocess
subprocess.call("command", timeout=20, shell=True)
Это вызовет команду и поднять исключение
subprocess.TimeoutExpired
, если команда не завершится через 20 секунд.
Затем вы можете обработать исключение, чтобы продолжить свой код, например:
try:
subprocess.call("command", timeout=20, shell=True)
except subprocess.TimeoutExpired:
# insert code here
Надеюсь, это поможет.
timeout
. Хотя упоминание об этом еще раз не повредит.
– jfs
23 February 2015 в 03:43
У меня возникла проблема в том, что я хотел завершить многопроцессорный подпроцесс, если потребовалось больше времени, чем заданная длина таймаута. Я хотел установить тайм-аут в Popen()
, но это не сработало. Затем я понял, что Popen().wait()
равен call()
, и поэтому у меня возникла идея установить тайм-аут в рамках метода .wait(timeout=xxx)
, который, наконец, работал. Таким образом, я решил это так:
import os
import sys
import signal
import subprocess
from multiprocessing import Pool
cores_for_parallelization = 4
timeout_time = 15 # seconds
def main():
jobs = [...YOUR_JOB_LIST...]
with Pool(cores_for_parallelization) as p:
p.map(run_parallel_jobs, jobs)
def run_parallel_jobs(args):
# Define the arguments including the paths
initial_terminal_command = 'C:\\Python34\\python.exe' # Python executable
function_to_start = 'C:\\temp\\xyz.py' # The multithreading script
final_list = [initial_terminal_command, function_to_start]
final_list.extend(args)
# Start the subprocess and determine the process PID
subp = subprocess.Popen(final_list) # starts the process
pid = subp.pid
# Wait until the return code returns from the function by considering the timeout.
# If not, terminate the process.
try:
returncode = subp.wait(timeout=timeout_time) # should be zero if accomplished
except subprocess.TimeoutExpired:
# Distinguish between Linux and Windows and terminate the process if
# the timeout has been expired
if sys.platform == 'linux2':
os.kill(pid, signal.SIGTERM)
elif sys.platform == 'win32':
subp.terminate()
if __name__ == '__main__':
main()
Существует идея подкласса класса Popen и расширения его с помощью некоторых простых декораторов методов. Назовем его ExpirablePopen.
from logging import error
from subprocess import Popen
from threading import Event
from threading import Thread
class ExpirablePopen(Popen):
def __init__(self, *args, **kwargs):
self.timeout = kwargs.pop('timeout', 0)
self.timer = None
self.done = Event()
Popen.__init__(self, *args, **kwargs)
def __tkill(self):
timeout = self.timeout
if not self.done.wait(timeout):
error('Terminating process {} by timeout of {} secs.'.format(self.pid, timeout))
self.kill()
def expirable(func):
def wrapper(self, *args, **kwargs):
# zero timeout means call of parent method
if self.timeout == 0:
return func(self, *args, **kwargs)
# if timer is None, need to start it
if self.timer is None:
self.timer = thr = Thread(target=self.__tkill)
thr.daemon = True
thr.start()
result = func(self, *args, **kwargs)
self.done.set()
return result
return wrapper
wait = expirable(Popen.wait)
communicate = expirable(Popen.communicate)
if __name__ == '__main__':
from subprocess import PIPE
print ExpirablePopen('ssh -T git@bitbucket.org', stdout=PIPE, timeout=1).communicate()
Хотя я не смотрел на него широко, этот декоратор , который я нашел в ActiveState, кажется довольно полезным для такого рода вещей. Наряду с subprocess.Popen(..., close_fds=True)
, по крайней мере, я готов для сценариев оболочки в Python.
Я успешно использовал killableprocess в Windows, Linux и Mac. Если вы используете Cygwin Python, вам понадобится версия killableprocess OSAF, потому что иначе родные процессы Windows не будут убиты.
Просто пытался написать что-то более простое.
#!/usr/bin/python
from subprocess import Popen, PIPE
import datetime
import time
popen = Popen(["/bin/sleep", "10"]);
pid = popen.pid
sttime = time.time();
waittime = 3
print "Start time %s"%(sttime)
while True:
popen.poll();
time.sleep(1)
rcode = popen.returncode
now = time.time();
if [ rcode is None ] and [ now > (sttime + waittime) ] :
print "Killing it now"
popen.kill()
Я не знаю, почему это не упоминается, но с Python 3.5 существует новая универсальная команда subprocess.run
(которая предназначена для замены check_call
, check_output
... ) и который имеет параметр timeout
.
subprocess.run (args, *, stdin = None, input = None, stdout = None, stderr = None, shell = False, cwd = None, timeout = None, check = False, encoding = None, errors = None)
Run the command described by args. Wait for command to complete, then return a CompletedProcess instance.
Он вызывает исключение
subprocess.TimeoutExpired
, когда время ожидания истекло.
Я реализовал то, что я мог бы собрать из нескольких из них. Это работает в Windows, и поскольку это вики сообщества, я полагаю, что я также поделился бы своим кодом:
class Command(threading.Thread):
def __init__(self, cmd, outFile, errFile, timeout):
threading.Thread.__init__(self)
self.cmd = cmd
self.process = None
self.outFile = outFile
self.errFile = errFile
self.timed_out = False
self.timeout = timeout
def run(self):
self.process = subprocess.Popen(self.cmd, stdout = self.outFile, \
stderr = self.errFile)
while (self.process.poll() is None and self.timeout > 0):
time.sleep(1)
self.timeout -= 1
if not self.timeout > 0:
self.process.terminate()
self.timed_out = True
else:
self.timed_out = False
Затем из другого класса или файла:
outFile = tempfile.SpooledTemporaryFile()
errFile = tempfile.SpooledTemporaryFile()
executor = command.Command(c, outFile, errFile, timeout)
executor.daemon = True
executor.start()
executor.join()
if executor.timed_out:
out = 'timed out'
else:
outFile.seek(0)
errFile.seek(0)
out = outFile.read()
err = errFile.read()
outFile.close()
errFile.close()
terminate()
отмечает поток как завершенный, но фактически не завершает поток! Я могу проверить это в * nix, но у меня нет компьютера Windows для тестирования.
– dotancohen
6 October 2013 в 10:50
никого не удивил, используя timeout
timeout 5 ping -c 3 somehost
Это не будет работать для каждого примера использования, но если вы имеете дело с простым скриптом, это
Также доступен как gtimeout в coreutils через homebrew
для пользователей Mac.
proc = subprocess.Popen(['/usr/bin/timeout', str(timeout)] + cmd, ...)
. Есть ли команда timeout
в Windows при запросе OP?
– jfs
21 April 2015 в 09:18
Другой вариант - записать во временный файл, чтобы предотвратить блокировку stdout вместо необходимости опроса с помощью функции connect (). Это работало для меня, где другие ответы не делали; например, на окнах.
outFile = tempfile.SpooledTemporaryFile()
errFile = tempfile.SpooledTemporaryFile()
proc = subprocess.Popen(args, stderr=errFile, stdout=outFile, universal_newlines=False)
wait_remaining_sec = timeout
while proc.poll() is None and wait_remaining_sec > 0:
time.sleep(1)
wait_remaining_sec -= 1
if wait_remaining_sec <= 0:
killProc(proc.pid)
raise ProcessIncompleteError(proc, timeout)
# read temp streams from start
outFile.seek(0);
errFile.seek(0);
out = outFile.read()
err = errFile.read()
outFile.close()
errFile.close()
import subprocess, optparse, os, sys, re, datetime, threading, time, glob, shutil, xml.dom.minidom, traceback
class OutputManager:
def __init__(self, filename, mode, console, logonly):
self.con = console
self.logtoconsole = True
self.logtofile = False
if filename:
try:
self.f = open(filename, mode)
self.logtofile = True
if logonly == True:
self.logtoconsole = False
except IOError:
print (sys.exc_value)
print ("Switching to console only output...\n")
self.logtofile = False
self.logtoconsole = True
def write(self, data):
if self.logtoconsole == True:
self.con.write(data)
if self.logtofile == True:
self.f.write(data)
sys.stdout.flush()
def getTimeString():
return time.strftime("%Y-%m-%d", time.gmtime())
def runCommand(command):
'''
Execute a command in new thread and return the
stdout and stderr content of it.
'''
try:
Output = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True).communicate()[0]
except Exception as e:
print ("runCommand failed :%s" % (command))
print (str(e))
sys.stdout.flush()
return None
return Output
def GetOs():
Os = ""
if sys.platform.startswith('win32'):
Os = "win"
elif sys.platform.startswith('linux'):
Os = "linux"
elif sys.platform.startswith('darwin'):
Os = "mac"
return Os
def check_output(*popenargs, **kwargs):
try:
if 'stdout' in kwargs:
raise ValueError('stdout argument not allowed, it will be overridden.')
# Get start time.
startTime = datetime.datetime.now()
timeoutValue=3600
cmd = popenargs[0]
if sys.platform.startswith('win32'):
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, shell=True)
elif sys.platform.startswith('linux'):
process = subprocess.Popen( cmd , stdout=subprocess.PIPE, shell=True )
elif sys.platform.startswith('darwin'):
process = subprocess.Popen( cmd , stdout=subprocess.PIPE, shell=True )
stdoutdata, stderrdata = process.communicate( timeout = timeoutValue )
retcode = process.poll()
####################################
# Catch crash error and log it.
####################################
OutputHandle = None
try:
if retcode >= 1:
OutputHandle = OutputManager( 'CrashJob_' + getTimeString() + '.txt', 'a+', sys.stdout, False)
OutputHandle.write( cmd )
print (stdoutdata)
print (stderrdata)
sys.stdout.flush()
except Exception as e:
print (str(e))
except subprocess.TimeoutExpired:
####################################
# Catch time out error and log it.
####################################
Os = GetOs()
if Os == 'win':
killCmd = "taskkill /FI \"IMAGENAME eq {0}\" /T /F"
elif Os == 'linux':
killCmd = "pkill {0)"
elif Os == 'mac':
# Linux, Mac OS
killCmd = "killall -KILL {0}"
runCommand(killCmd.format("java"))
runCommand(killCmd.format("YouApp"))
OutputHandle = None
try:
OutputHandle = OutputManager( 'KillJob_' + getTimeString() + '.txt', 'a+', sys.stdout, False)
OutputHandle.write( cmd )
except Exception as e:
print (str(e))
except Exception as e:
for frame in traceback.extract_tb(sys.exc_info()[2]):
fname,lineno,fn,text = frame
print "Error in %s on line %d" % (fname, lineno)
Вот мое решение, я использовал Thread и Event:
import subprocess
from threading import Thread, Event
def kill_on_timeout(done, timeout, proc):
if not done.wait(timeout):
proc.kill()
def exec_command(command, timeout):
done = Event()
proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
watcher = Thread(target=kill_on_timeout, args=(done, timeout, proc))
watcher.daemon = True
watcher.start()
data, stderr = proc.communicate()
done.set()
return data, stderr, proc.returncode
В действии:
In [2]: exec_command(['sleep', '10'], 5)
Out[2]: ('', '', -9)
In [3]: exec_command(['sleep', '10'], 11)
Out[3]: ('', '', 0)
, если вы используете python 2, попробуйте
import subprocess32
try:
output = subprocess32.check_output(command, shell=True, timeout=3)
except subprocess32.TimeoutExpired as e:
print e
После того, как вы поймете, что все машины, работающие с полным процессом, в * unix, вы легко найдете более простое решение:
Рассмотрим этот простой пример, как сделать timeoutable communication () meth с помощью select.select () (доступно почти каждый on * nix в настоящее время). Это также можно записать с помощью epoll / poll / kqueue, но вариант select.select () может быть хорошим примером для вас. И основные ограничения select.select () (speed и 1024 max fds) не применимы для вашей задачи.
Это работает под * nix, не создает потоки, не использует сигналы, может быть выделено из любой поток (не только основной) и достаточно быстрый, чтобы читать 250 мб / с данных из stdout на моей машине (i5 2.3ghz).
В конце есть проблема в joinsting stdout / stderr связи. Если у вас огромный выход программы, это может привести к большому использованию памяти. Но вы можете вызывать связь () несколько раз с меньшими тайм-аутами.
class Popen(subprocess.Popen):
def communicate(self, input=None, timeout=None):
if timeout is None:
return subprocess.Popen.communicate(self, input)
if self.stdin:
# Flush stdio buffer, this might block if user
# has been writing to .stdin in an uncontrolled
# fashion.
self.stdin.flush()
if not input:
self.stdin.close()
read_set, write_set = [], []
stdout = stderr = None
if self.stdin and input:
write_set.append(self.stdin)
if self.stdout:
read_set.append(self.stdout)
stdout = []
if self.stderr:
read_set.append(self.stderr)
stderr = []
input_offset = 0
deadline = time.time() + timeout
while read_set or write_set:
try:
rlist, wlist, xlist = select.select(read_set, write_set, [], max(0, deadline - time.time()))
except select.error as ex:
if ex.args[0] == errno.EINTR:
continue
raise
if not (rlist or wlist):
# Just break if timeout
# Since we do not close stdout/stderr/stdin, we can call
# communicate() several times reading data by smaller pieces.
break
if self.stdin in wlist:
chunk = input[input_offset:input_offset + subprocess._PIPE_BUF]
try:
bytes_written = os.write(self.stdin.fileno(), chunk)
except OSError as ex:
if ex.errno == errno.EPIPE:
self.stdin.close()
write_set.remove(self.stdin)
else:
raise
else:
input_offset += bytes_written
if input_offset >= len(input):
self.stdin.close()
write_set.remove(self.stdin)
# Read stdout / stderr by 1024 bytes
for fn, tgt in (
(self.stdout, stdout),
(self.stderr, stderr),
):
if fn in rlist:
data = os.read(fn.fileno(), 1024)
if data == '':
fn.close()
read_set.remove(fn)
tgt.append(data)
if stdout is not None:
stdout = ''.join(stdout)
if stderr is not None:
stderr = ''.join(stderr)
return (stdout, stderr)
Предоставление команды Linux timeout
не является плохим обходным решением, и это сработало для меня.
cmd = "timeout 20 "+ cmd
subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(output, err) = p.communicate()
https://pypi.python.org/pypi/python-subprocess2 предоставляет расширения модуля подпроцесса, которые позволяют подождать до определенного периода времени, в противном случае прекратить работу.
Итак, подождите до 10 секунд для завершения процесса, иначе kill:
pipe = subprocess.Popen('...')
timeout = 10
results = pipe.waitOrTerminate(timeout)
Это совместимо с обоими окнами и unix. «results» - это словарь, он содержит «returnCode», который является возвратом приложения (или «Нет», если он должен быть убит), а также «actionTaken». который будет «SUBPROCESS2_PROCESS_COMPLETED», если процесс завершен в обычном режиме, или маску «SUBPROCESS2_PROCESS_TERMINATED» и SUBPROCESS2_PROCESS_KILLED в зависимости от предпринятых действий (см. документацию для полной информации)
timeout
- packages.ubuntu.com/search?keywords=timeout - но ни один из них не работает в Windows, не так ли?
– Sridhar Ratnakumar
16 December 2011 в 20:00
shell=True
. – tripleee 11 September 2014 в 15:57