Argumentos de seqüência de caracteres de segmentação em Python

156

Eu tenho um problema com o Python threading e o envio de uma string nos argumentos.

def processLine(line) :
    print "hello";
    return;

.

dRecieved = connFile.readline();
processThread = threading.Thread(target=processLine, args=(dRecieved));
processThread.start();

Onde dRecieved é a sequência de uma linha lida por uma conexão. Ele chama uma função simples que, a partir de agora, tem apenas um trabalho de impressão "olá".

No entanto, recebo o seguinte erro

Traceback (most recent call last):
File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
self.run()
File "C:\Python25\lib\threading.py", line 446, in run
self.__target(*self.__args, **self.__kwargs)
TypeError: processLine() takes exactly 1 arguments (232 given)

232 é o comprimento da string que estou tentando passar, então acho que está dividindo em cada caractere e tentando passar os argumentos assim. Funciona bem se eu apenas chamar a função normalmente, mas realmente gostaria de configurá-la como um thread separado.

Anônimo
fonte
49
Por que você tem ponto e vírgula no final de cada linha?
Maikflow 21/09/2015
@Maikflow Não é uma boa prática? O ASI converte linhas não-ponto-e-vírgula em ponto-e-vírgula no fundo depois.
IK

Respostas:

296

Você está tentando criar uma tupla, mas está apenas parênteses uma string :)

Adicione um ',' extra:

dRecieved = connFile.readline()
processThread = threading.Thread(target=processLine, args=(dRecieved,))  # <- note extra ','
processThread.start()

Ou use colchetes para fazer uma lista:

dRecieved = connFile.readline()
processThread = threading.Thread(target=processLine, args=[dRecieved])  # <- 1 element list
processThread.start()

Se você observar, no rastreamento de pilha: self.__target(*self.__args, **self.__kwargs)

O *self.__argstransforma seu string em uma lista de caracteres, passando-os para a processLine função. Se você passar uma lista de um elemento, ele passará esse elemento como o primeiro argumento - no seu caso, a string.

Stephen
fonte
1
parênteses extras no final da linha dois do segundo bloco de código. Eu queria editá-lo, mas é menos que 6 caracteres
harmonickey
Se você tiver arg2 com valor padrão, faça isso. threading.Thread(target=thread_function, args=(arg1,),kwargs={'arg2': arg2})
DeveScie
8

Espero fornecer mais conhecimento de base aqui.

Primeiro, assinatura do construtor do método threading :: Thread :

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

args é a tupla de argumentopara a chamada de destino. O padrão é ().

Segundo, uma peculiaridade em Python sobre tuple:

Tuplas vazias são construídas por um par de parênteses vazios; uma tupla com um item é construída seguindo um valor com vírgula (não é suficiente colocar um único valor entre parênteses).

Por outro lado, uma string é uma sequência de caracteres, como 'abc'[1] == 'b'. Portanto, se enviar uma string para args, mesmo entre parênteses (ainda uma picada), cada caractere será tratado como um único parâmetro.

No entanto, o Python é tão integrado e não é como o JavaScript, onde argumentos extras podem ser tolerados. Em vez disso, lança um TypeErrorpara reclamar.

themefield
fonte