Is there a way to send a file using POST from a Python script?
                +6 
                A: 
                
                
              
            Yes. You'd use the urllib2 module, and encode using the multipart/form-data content type. Here is some sample code to get you started -- it's a bit more than just file uploading, but you should be able to read through it and see how it works:
user_agent = "image uploader"
default_message = "Image $current of $total"
import logging
import os
from os.path import abspath, isabs, isdir, isfile, join
import random
import string
import sys
import mimetypes
import urllib2
import httplib
import time
import re
def random_string (length):
    return ''.join (random.choice (string.letters) for ii in range (length + 1))
def encode_multipart_data (data, files):
    boundary = random_string (30)
    def get_content_type (filename):
     return mimetypes.guess_type (filename)[0] or 'application/octet-stream'
    def encode_field (field_name):
     return ('--' + boundary,
             'Content-Disposition: form-data; name="%s"' % field_name,
             '', str (data [field_name]))
    def encode_file (field_name):
     filename = files [field_name]
     return ('--' + boundary,
             'Content-Disposition: form-data; name="%s"; filename="%s"' % (field_name, filename),
             'Content-Type: %s' % get_content_type(filename),
             '', open (filename, 'rb').read ())
    lines = []
    for name in data:
     lines.extend (encode_field (name))
    for name in files:
     lines.extend (encode_file (name))
    lines.extend (('--%s--' % boundary, ''))
    body = '\r\n'.join (lines)
    headers = {'content-type': 'multipart/form-data; boundary=' + boundary,
               'content-length': str (len (body))}
    return body, headers
def send_post (url, data, files):
    req = urllib2.Request (url)
    connection = httplib.HTTPConnection (req.get_host ())
    connection.request ('POST', req.get_selector (),
                        *encode_multipart_data (data, files))
    response = connection.getresponse ()
    logging.debug ('response = %s', response.read ())
    logging.debug ('Code: %s %s', response.status, response.reason)
def make_upload_file (server, thread, delay = 15, message = None,
                      username = None, email = None, password = None):
    delay = max (int (delay or '0'), 15)
    def upload_file (path, current, total):
     assert isabs (path)
     assert isfile (path)
     logging.debug ('Uploading %r to %r', path, server)
     message_template = string.Template (message or default_message)
     data = {'MAX_FILE_SIZE': '3145728',
             'sub': '',
             'mode': 'regist',
             'com': message_template.safe_substitute (current = current, total = total),
             'resto': thread,
             'name': username or '',
             'email': email or '',
             'pwd': password or random_string (20),}
     files = {'upfile': path}
     send_post (server, data, files)
     logging.info ('Uploaded %r', path)
     rand_delay = random.randint (delay, delay + 5)
     logging.debug ('Sleeping for %.2f seconds------------------------------\n\n', rand_delay)
     time.sleep (rand_delay)
    return upload_file
def upload_directory (path, upload_file):
    assert isabs (path)
    assert isdir (path)
    matching_filenames = []
    file_matcher = re.compile (r'\.(?:jpe?g|gif|png)$', re.IGNORECASE)
    for dirpath, dirnames, filenames in os.walk (path):
     for name in filenames:
      file_path = join (dirpath, name)
      logging.debug ('Testing file_path %r', file_path)
      if file_matcher.search (file_path):
       matching_filenames.append (file_path)
      else:
       logging.info ('Ignoring non-image file %r', path)
    total_count = len (matching_filenames)
    for index, file_path in enumerate (matching_filenames):
     upload_file (file_path, index + 1, total_count)
def run_upload (options, paths):
    upload_file = make_upload_file (**options)
    for arg in paths:
     path = abspath (arg)
     if isdir (path):
      upload_directory (path, upload_file)
     elif isfile (path):
      upload_file (path)
     else:
      logging.error ('No such path: %r' % path)
    logging.info ('Done!')
                  John Millikin
                   2008-09-16 01:21:20
                
              
                
                A: 
                
                
              
              import urllib2
if __name__ == "__main__":
    conn = urllib2.urlopen(u"http://localhost/someurl.cgi", 
                           u"This is your POST data")
    # Do something with the response.
Why are people voting this answer up? It's got nothing to do with uploading files.
                  John Millikin
                   2008-09-17 00:07:44
                I needed to post contents of a file to a server-side script, and urllib2.urlopen has worked just fine for me.
                  che
                   2008-11-21 02:09:46
                
                +10 
                A: 
                
                
              Blatant self-promotion:
check out my poster module for python. It handles the multipart/form-data encoding, as well as supporting streaming uploads (so you don't have to load the entire file into memory before submitting the HTTP POST request).
                  Chris AtLee
                   2008-09-16 18:05:01
                
              
                +1 
                A: 
                
                
              
            Chris Atlee's poster library works really well for this (particularly the convenience function poster.encode.multipart_encode()). As a bonus, it supports streaming of large files without loading an entire file into memory. See also Python issue 3244.
                  gotgenes
                   2009-02-08 05:20:36