sql >> Database teknologi >  >> RDS >> Mysql

Hvorfor venter subprocess.Popen ikke, indtil den underordnede proces afsluttes?

subprocess.Popen , når den instansieres, kører programmet. Den venter dog ikke på den – den affyrer den i baggrunden, som om du havde skrevet cmd & i en skal. Så i koden ovenfor har du i det væsentlige defineret en race-tilstand -- hvis indsatserne kan afslutte i tide, vil det se normalt ud, men hvis ikke får du det uventede output. Du venter ikke på din første run() Hvis PID er færdig, returnerer du blot dens Popen instans og fortsætter.

Jeg er ikke sikker på, hvordan denne adfærd modsiger dokumentationen, for der er nogle meget klare metoder på Popen, der synes at indikere, at den ikke er ventet på, f.eks.:

Popen.wait()
  Wait for child process to terminate. Set and return returncode attribute.

Jeg er dog enig i, at dokumentationen for dette modul kunne forbedres.

For at vente på, at programmet er færdig, vil jeg anbefale at bruge subprocess 's bekvemmelighedsmetode, subprocess.call , eller ved at bruge communicate på en Popen objekt (til det tilfælde, hvor du har brug for stdout). Du gør allerede dette til dit andet opkald.

### START MAIN
# copy some rows from a source table to a destination table
# note that the destination table is empty when this script is run
cmd = 'mysql -u ve --skip-column-names --batch --execute="insert into destination (select * from source limit 100000)" test'
subprocess.call(cmd)

# check to see how many rows exist in the destination table
cmd = 'mysql -u ve --skip-column-names --batch --execute="select count(*) from destination" test'
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
try: count = (int(process.communicate()[0][:-1]))
except: count = 0

Derudover behøver du i de fleste tilfælde ikke at køre kommandoen i en shell. Dette er et af disse tilfælde, men du bliver nødt til at omskrive din kommando som en sekvens. Hvis du gør det på den måde, kan du også undgå traditionel skalinjektion og bekymre dig mindre om at citere, som sådan:

prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)

Dette vil endda virke og vil ikke injicere, som du ville forvente:

prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)

Prøv det interaktivt. Du undgår mulighederne for skalinjektion, især hvis du accepterer brugerinput. Jeg formoder, at du bruger den mindre fantastiske streng-metode til at kommunikere med underprocessen, fordi du løb ind i problemer med at få sekvenserne til at fungere :^)



  1. Hvordan skal jeg undslippe tegn i denne LIKE-forespørgsel?

  2. Rekursion på databaseforespørgsel for at få hierarkiske resultater ved hjælp af Hibernate - Java

  3. Hvorfor PostgreSQL-adapter psycopg2 fejler i Google App Engine dev_appserver.py?

  4. RMAN fejler med RMAN-06900 RMAN-06901 ORA-04031